Text as tooltip, popup or labels in folium choropleth GeoJSON polygons
Question:
Folium allow to create Markers with tooltip or popup text. I would like to do the same with my GeoJSON polygons.
My GeoJSON has a property called "name"
(feature.properties.name
-> let’s assume it is the name of each US state). I would like to be able to display this as a label in my choropleth map, in addition to the unemployment rate in each state. I also have the same information in the "State"
column from the pandas dataframe
.
Is this possible? I would be happy with a solution that allows this to be a popup, tooltip or a simple text label written on top.
import pandas as pd
url = (
"https://raw.githubusercontent.com/python-visualization/folium/master/examples/data"
)
state_geo = f"{url}/us-states.json"
state_unemployment = f"{url}/US_Unemployment_Oct2012.csv"
state_data = pd.read_csv(state_unemployment)
m = folium.Map(location=[48, -102], zoom_start=3)
folium.Choropleth(
geo_data=state_geo,
name="choropleth",
data=state_data,
columns=["State", "Unemployment"],
key_on="feature.id",
fill_color="YlGn",
fill_opacity=0.7,
line_opacity=0.2,
legend_name="Unemployment Rate (%)",
).add_to(m)
folium.LayerControl().add_to(m)
m
Answers:
I’ve had to use folium’s GeoJsonTooltip() and some other steps to get this done in the past. I’m curious to know if someone has a better way
- Capture the return value of the Choropleth function
- Add a value(eg unemployment) to the Chorpleth’s underlying geojson obj
- Create GeoJsonTooltip with that value from step 2
- Add that tooltip to the choropleth’s geojson
url = (
"https://raw.githubusercontent.com/python-visualization/folium/master/examples/data"
)
state_geo = f"{url}/us-states.json"
state_unemployment = f"{url}/US_Unemployment_Oct2012.csv"
state_data = pd.read_csv(state_unemployment)
m = folium.Map(location=[48, -102], zoom_start=3)
# capturing the return of folium.Choropleth()
cp = folium.Choropleth(
geo_data=state_geo,
name="choropleth",
data=state_data,
columns=["State", "Unemployment"],
key_on="feature.id",
fill_color="YlGn",
fill_opacity=0.7,
line_opacity=0.2,
legend_name="Unemployment Rate (%)",
).add_to(m)
# creating a state indexed version of the dataframe so we can lookup values
state_data_indexed = state_data.set_index('State')
# looping thru the geojson object and adding a new property(unemployment)
# and assigning a value from our dataframe
for s in cp.geojson.data['features']:
s['properties']['unemployment'] = state_data_indexed.loc[s['id'], 'Unemployment']
# and finally adding a tooltip/hover to the choropleth's geojson
folium.GeoJsonTooltip(['name', 'unemployment']).add_to(cp.geojson)
folium.LayerControl().add_to(m)
m
Bob’s solution works well. Two notes:
- For this to work, you need to have values in the data table (here: groupValues) for all the entries in the geo_data= table (here: counties) specified in the folium.Choropleth definition.
cp = folium.Choropleth(
geo_data = counties,
name = 'choropleth',
data = groupValues,
etc.
If an entry in the geo_data table lacks a corresponding value in data table, the loop will throw a KeyError
. To fix this, I created a loop that uses try . . . except
to add the correct values to the geojson table.
- I was able to add numerical data (float64) to the cp.geojson table and folium allowed me to add it with the GeoJsonTooltip and LayerControl, but when I tried to display the map, I got an "float64 data cannot be serialized" error. I fixed this by converting it to a string before adding it to the cp.geojson table.
The working loop looks like this:
for row in cp.geojson.data['features']:
try:
row['properties']['PctAllPop'] = str(groupValues.loc[row['properties']['FIPS'],'PctAllPop'])
except KeyError:
row['properties']['PctAllPop'] = 'No adherents'
folium.GeoJsonTooltip(['NAME','PctAllPop'],aliases=['County:','Pct total pop:']).add_to(cp.geojson)
Folium allow to create Markers with tooltip or popup text. I would like to do the same with my GeoJSON polygons.
My GeoJSON has a property called "name"
(feature.properties.name
-> let’s assume it is the name of each US state). I would like to be able to display this as a label in my choropleth map, in addition to the unemployment rate in each state. I also have the same information in the "State"
column from the pandas dataframe
.
Is this possible? I would be happy with a solution that allows this to be a popup, tooltip or a simple text label written on top.
import pandas as pd
url = (
"https://raw.githubusercontent.com/python-visualization/folium/master/examples/data"
)
state_geo = f"{url}/us-states.json"
state_unemployment = f"{url}/US_Unemployment_Oct2012.csv"
state_data = pd.read_csv(state_unemployment)
m = folium.Map(location=[48, -102], zoom_start=3)
folium.Choropleth(
geo_data=state_geo,
name="choropleth",
data=state_data,
columns=["State", "Unemployment"],
key_on="feature.id",
fill_color="YlGn",
fill_opacity=0.7,
line_opacity=0.2,
legend_name="Unemployment Rate (%)",
).add_to(m)
folium.LayerControl().add_to(m)
m
I’ve had to use folium’s GeoJsonTooltip() and some other steps to get this done in the past. I’m curious to know if someone has a better way
- Capture the return value of the Choropleth function
- Add a value(eg unemployment) to the Chorpleth’s underlying geojson obj
- Create GeoJsonTooltip with that value from step 2
- Add that tooltip to the choropleth’s geojson
url = (
"https://raw.githubusercontent.com/python-visualization/folium/master/examples/data"
)
state_geo = f"{url}/us-states.json"
state_unemployment = f"{url}/US_Unemployment_Oct2012.csv"
state_data = pd.read_csv(state_unemployment)
m = folium.Map(location=[48, -102], zoom_start=3)
# capturing the return of folium.Choropleth()
cp = folium.Choropleth(
geo_data=state_geo,
name="choropleth",
data=state_data,
columns=["State", "Unemployment"],
key_on="feature.id",
fill_color="YlGn",
fill_opacity=0.7,
line_opacity=0.2,
legend_name="Unemployment Rate (%)",
).add_to(m)
# creating a state indexed version of the dataframe so we can lookup values
state_data_indexed = state_data.set_index('State')
# looping thru the geojson object and adding a new property(unemployment)
# and assigning a value from our dataframe
for s in cp.geojson.data['features']:
s['properties']['unemployment'] = state_data_indexed.loc[s['id'], 'Unemployment']
# and finally adding a tooltip/hover to the choropleth's geojson
folium.GeoJsonTooltip(['name', 'unemployment']).add_to(cp.geojson)
folium.LayerControl().add_to(m)
m
Bob’s solution works well. Two notes:
- For this to work, you need to have values in the data table (here: groupValues) for all the entries in the geo_data= table (here: counties) specified in the folium.Choropleth definition.
cp = folium.Choropleth(
geo_data = counties,
name = 'choropleth',
data = groupValues,
etc.
If an entry in the geo_data table lacks a corresponding value in data table, the loop will throw a KeyError
. To fix this, I created a loop that uses try . . . except
to add the correct values to the geojson table.
- I was able to add numerical data (float64) to the cp.geojson table and folium allowed me to add it with the GeoJsonTooltip and LayerControl, but when I tried to display the map, I got an "float64 data cannot be serialized" error. I fixed this by converting it to a string before adding it to the cp.geojson table.
The working loop looks like this:
for row in cp.geojson.data['features']:
try:
row['properties']['PctAllPop'] = str(groupValues.loc[row['properties']['FIPS'],'PctAllPop'])
except KeyError:
row['properties']['PctAllPop'] = 'No adherents'
folium.GeoJsonTooltip(['NAME','PctAllPop'],aliases=['County:','Pct total pop:']).add_to(cp.geojson)