Simple map of communties with hair sample collection status
Code
```{python}# load in list of people who did the hair sampleHAIR_SAMPLE = "/Users/st2246/Work/Pilot3/data/raw/main/09. Hair Cortisol/hair_sampled list from TRL.dta"hair_sample_list = pd.read_stata(HAIR_SAMPLE, convert_categoricals=False)hair_sample_list["hh_id"] = hair_sample_list["compid"].astype("int64")# As inthair_sample_list["sample_collected"] = ( hair_sample_list["sample_status"] == "YES").astype("int32")hair_sample_list["sample_refused"] = (hair_sample_list["sample_status"] == "NO").astype( "int32")hair_sample_list["sample_NA"] = (hair_sample_list["sample_status"] == "N.A").astype( "int32")```
Code
```{python}# Aggregate to community leveldf = ( hair_sample_list.groupby(["community_id"]) .agg( num_hh=("hh_id", "nunique"), sample_collected=("sample_collected", "sum"), sample_refused=("sample_refused", "sum"), sample_NA=("sample_NA", "sum"), ) .reset_index())```
Below is an interactive map that plots hair sample collection progress for all communities.
Note
Note: highlighted communities have at least 5 households whose hair sample is missing (not collected & not refused). The size of the circle is proportional to the number of households whose hair sample is missing. The color indicates the district.
Hover over a community to see the exact counts.
Code
```{python}import foliumfrom folium.plugins import Draw# Create a map centered on a locationm = folium.Map( location=[communities["centroid_lat"].mean(), communities["centroid_lon"].mean()], zoom_start=9,)m2 = folium.Map( location=[communities["centroid_lat"].mean(), communities["centroid_lon"].mean()], zoom_start=9,)# 3. Define a simple function to assign a color based on the 'category' columndef get_color(row, desaturate: bool): district = row["district"] if district.lower() == "karaga": color = "lightblue" if desaturate else "darkblue" elif district.lower() == "mion": color = "lightgreen" if desaturate else "darkgreen" elif district.lower() == "tolon": # light gray hex color = "gray" if desaturate else "black" else: color = "pink" if desaturate else "red" return color# 4. Loop through each row in the DataFrame to add a CircleMarkerfor idx, row in communities.iterrows(): radius = row["sample_NA"] * 40 info_text = f""" Community: {row["community"]}<br> Estimated Cpds: {row["estimated_compounds"]}<br> Households: {row["num_hh"]}<br> Sample Collected: {row["sample_collected"]}<br> Sample Refused: {row["sample_refused"]} ({row["sample_refused"] /(row["sample_refused"] + row["sample_collected"]):.1%} of attempts refused) <br> Sample Missing: {row["sample_NA"]} ({row["sample_NA"] / row["num_hh"]:.1%}) """ desaturate = row["sample_NA"] < 5 fill = get_color(row, desaturate) border = get_color(row, desaturate) # Add the CircleMarker to the map circle = folium.Circle( location=[row["centroid_lat"], row["centroid_lon"]], radius=radius, color=border, fill=True, fill_color=fill, fill_opacity=1, popup=info_text, tooltip=info_text, ) circle2 = folium.Circle( location=[row["centroid_lat"], row["centroid_lon"]], radius=radius, color=border, fill=False, popup=info_text, tooltip=info_text, ) if ( row["sample_NA"] > 0 and row["sample_refused"] / (row["sample_refused"] + row["sample_collected"]) < 0.5 ): circle.add_to(m) elif ( row["sample_NA"] > 0 and row["sample_refused"] / (row["sample_refused"] + row["sample_collected"]) >= 0.35 ): circle2.add_to(m)```
Note
Map only includes communities with at least one household whose hair sample is missing. If everyone in the communitie has had their hair sample collected OR refused their collection, then they are ommitted from the map.
Code
```{python}m```
Make this Notebook Trusted to load map: File -> Trust Notebook