Reputation: 33
I've got a geoJson file with a bunch of features which I'm trying to display on an interactive folium map and I'm trying to add a plotly graph that pops up when you click on a polygon. At this moment I already have a folder with all plotly graphs for each city, 'currentWorkingDirectory/graphs/CityName.HTML'. I also have the interactive folium map with the different polygons which I can hover over or click for a popup.
Now I'm having trouble with adding the plotly graphs as a html string to the geojson popups. Could someone help me with this? I'll add a code snippet of the folium map and what I've tried:
import folium
import geopandas as gpd
import codecs
map = folium.Map(location=['51.096246199999996', '4.178629103169916'], tiles="cartodbpositron", zoom_start=9)
geojson_file_df = gpd.read_file('Refgem_geojson.json')
loc = 'Project GEO ICT'
title_html = '''
<h3 align="center" style="font-size:20px"><b>{}</b></h3>
'''.format(loc)
map.get_root().html.add_child(folium.Element(title_html))
g_map = folium.GeoJson(
geojson_file,
name="GeoJson",
style_function=lambda x: {'fillColor': 'orange'}
).add_to(map)
folium.GeoJsonTooltip(
fields=['NISCODE','NAAM', 'OPPERVL'],
aliases=['NISCODE', 'Naam', 'Oppervlakte'],
sticky=False
).add_to(g_map)
folium.GeoJsonPopup(
fields=["NAAM", "Average Prices: " ,"Woonhuis", "Villa", "Studio"],
aliases=["Naam", "Average Prices: ","Woonhuis", "Villa", "Studio"]
).add_to(g_map)
html="""
<iframe src=\"""" + codecs.open("graphs/AARTSELAAR.html", 'r').read() + """\" width="850" height="400" frameborder="0">
"""
popup1 = folium.Popup(folium.Html(html, script=True))
folium.Marker(['51.096246199999996','4.178629103169916'],popup=popup1,icon=folium.Icon( icon='home', prefix='fa')).add_to(map)
map
Here ^ I tried to add the popup to a marker, but that didn't work for me (it's also not really what I want, I want to add the popup to a polygon). I believe I should make some sort of loop that iterates over all features in the geoJson and adds a popup for every iteration.
Upvotes: 1
Views: 424
Reputation: 31236
You have not provided sample data / geometry so used standard geopandas sample data
GeoJsonPopup()
but found no solutionimport geopandas as gpd
import folium
from statistics import mean
import plotly.express as px
import base64, io
# some geometry
gdf = gpd.read_file(gpd.datasets.get_path("naturalearth_lowres")).loc[
lambda d: d["continent"].eq("Europe") & ~d.bounds.lt(-30).any(axis=1)
]
# create the map, nicely centered and zoomed
bounds = gdf.total_bounds
x = mean([bounds[0], bounds[2]])
y = mean([bounds[1], bounds[3]])
location = (y, x)
m = folium.Map(location=location)
m.fit_bounds([[bounds[1], bounds[0]], [bounds[3], bounds[2]]])
# given need to create a geojson layer for each figure, create
# feature group to contain them
fg = folium.FeatureGroup(name="Europe", show=False)
# create an encocded image of graph...
# change to generate graph you want
def b64image(vals=[1, 2]):
fig = (
px.pie(values=vals)
.update_layout(margin={"l": 0, "r": 0, "t": 0, "b": 0})
.update_traces(texttemplate="%{percent:.0%}")
)
b = io.BytesIO(fig.to_image(format="png", width=80, height=80))
b64 = base64.b64encode(b.getvalue())
return "data:image/png;base64," + b64.decode("utf-8")
tot_pop = gdf["pop_est"].sum()
# create a geojson layer for each feature
for i, r in gdf.iterrows():
# geodataframe of row
gdf_ = gpd.GeoDataFrame(r.to_frame().T, crs=gdf.crs)
# URI encoded image of plotly figure
img_ = f'<img src="{b64image([r["pop_est"], tot_pop-r["pop_est"]])}"/>'
choro_ = folium.GeoJson(
gdf_.__geo_interface__,
name=r["name"],
style_function=lambda x: {"fillColor": "orange"},
tooltip=folium.GeoJsonTooltip(gdf_.drop(columns="geometry").columns.tolist()),
)
# this is the real work around, add to layer which is a choro
folium.Popup(img_).add_to(choro_)
choro_.add_to(fg)
fg.add_to(m)
m
Upvotes: 1