Folium is a Python library for creating interactive maps. The plotted markers or polygons can be assigned to individual layers (using folium.FeatureGroup()
), which can be switched on and off with a mouse click.
All the examples I found on the net explicitly define each individual layer with a command like:
feature_group1 = FeatureGroup(name='Foo')
If I have categorical data in a Geopandas.GeoDataFrame, I certainly don’t want to create a layer for each category by hand. Fortunately, we can automate this by simply appending each initialised FeatureGroup to a list. Here’s an example with volcanoes.
A quick look at the data:
volcanoes.info()RangeIndex: 1233 entries, 0 to 1232 Data columns (total 13 columns): # Column Non-Null Count Dtype --- ------ -------------- ----- 0 number 1233 non-null int64 1 name 1233 non-null object 2 country 1233 non-null object 3 vtype 1233 non-null object 4 evidence 1233 non-null object 5 last_eruption 1233 non-null object 6 region 1233 non-null object 7 subregion 1233 non-null object 8 elevation 1233 non-null int64 9 rocks 1198 non-null object 10 tectonic_setting 1230 non-null object 11 last_eruption_int 787 non-null float64 12 geometry 1233 non-null geometry dtypes: float64(1), geometry(1), int64(2), object(9) memory usage: 125.4+ KB
I want a map grouped by rock type.
grouped = volcanoes.groupby('rocks')
Since Seaborn’s colour palettes are particularly nice, I use them to create a list of colours in hex format (as used by html). The number of colours needed is len(grouped)
.
import seaborn as sns pal = sns.color_palette("husl", len(grouped)).as_hex()
In this example I do not want the base map (the tile layer) to be displayed in the LayerControl as well. Therefore I initialise the map without tiles and add a TileLayer with control=False
:
m = folium.Map(tiles=None) folium.TileLayer('cartodbpositron', control=False).add_to(m)
Now we iterate through the grouped GeoDataFrame. For each category a FeatureGroup is created, which is appended to the list f_groups. Then markers for corresponding volcanoes are added to the last initialised FeatureGroup.
f_groups = [] for group_name, group_data in grouped: f_groups.append(folium.FeatureGroup(group_name)) color = pal.pop() for i in range(0,len(group_data)): # html for popup of markers html=f""" <h2> {group_data.iloc[i]['name']} </h2> <small> <p> Country: {group_data.iloc[i]['country']} <br/> Elevation: {group_data.iloc[i]['elevation']} <br/> Last Eruption: {group_data.iloc[i]['last_eruption']} <br/> Rocks: {group_data.iloc[i]['rocks']} <br/> Tectonic Setting: {group_data.iloc[i]['tectonic_setting']} </p> </small> """ iframe = folium.IFrame(html=html, width=300, height=200) popup = folium.Popup(iframe, max_width=650) # Add markers to last FeatureGroup folium.CircleMarker( location=[group_data.iloc[i].geometry.y, group_data.iloc[i].geometry.x], radius=5, popup=popup, tooltip=group_data.iloc[i]['name'], fill_color=color, stroke = False, fill_opacity = 1, ).add_to(f_groups[-1]) # Add last featureGroup to Map f_groups[-1].add_to(m) folium.LayerControl().add_to(m) m