我的目标是利用
ipywidgets
dropdowns 和 Folium
来过滤和可视化地理数据框。作为示例,让我们考虑一个源自自然地球向量的地理数据框,其中包含“大陆”和“名称”等列。
我的目标是创建一个用户界面,用户可以首先从下拉列表中选择一个大陆。选择后,另一个下拉列表会动态填充该大陆内的国家/地区。最后,当从第二个下拉列表中选择一个国家/地区时,其位置将显示在 Folium 地图上。
我打算将此交互式笔记本另存为 HTML 文件。
下面是我迄今为止尝试过的代码,基于How do add drop down menu for the folium map?
import geopandas as gpd
import ipywidgets
from IPython.display import HTML, display
import folium
df = gpd.read_file(gpd.datasets.get_path("naturalearth_lowres"))
df = df[['continent', 'geometry']]
out = ipywidgets.Output(layout={'border': '1px solid black'})
w = ipywidgets.Dropdown(
options=df['continent'].unique().tolist(),
value=df['continent'].tolist()[0],
description='Column:',
disabled=False,
)
# Define a function to filter the dataframe
def filter_dataframe(name):
return df[df['continent'] == name]
def on_dropdown_change(change):
out.clear_output()
df = filter_dataframe(w.value)
with out:
display(df.explore(df.columns[0], cmap="Blues"))
w.observe(on_dropdown_change, names='value')
display(w)
with out:
display(df.explore(df.columns[0], cmap="Blues"))
out
我对 ipywidgets 没有足够的经验。我将在序言中说,可能有更好的代码,但基于 SO 中的answers,我配置了一个包含大陆选择的字典以及与该大陆相关的国家/地区列表。第一个下拉列表中的处理程序具有由大陆选择结果设置的国家/地区列表,第二个下拉列表按大陆值和国家/地区值提取数据帧。
import geopandas as gpd
import ipywidgets
from IPython.display import HTML, display
import folium
import mapclassify
df = gpd.read_file(gpd.datasets.get_path("naturalearth_lowres"))
continent_group = {}
continent_list = df.continent.unique()[:6]
continent_list.insert(0, 'all')
for c in continent_list:
dff = df.query('continent == @c')
continent_group[c] = dff['name'].tolist()
df = df[['continent', 'name', 'geometry']]
out = ipywidgets.Output(layout={'border': '1px solid black'})
w = ipywidgets.Dropdown(
options=continent_list,
value=continent_list[0],
description='Continet:',
disabled=False,
)
c = ipywidgets.Dropdown(
description='Counrty:',
disabled=False,
)
def continent_update(x):
country_list = continent_group[x]
c.options = country_list
# Define a function to filter the dataframe
def filter_dataframe(continent_name, country_name):
#print('country_name:', country_name)
if country_name is None:
return df[df['continent'] == continent_name]
else:
return df[(df['continent'] == continent_name) & (df['name'] == country_name)]
def dropdown_eventhandler1(change):
print('w.value',w.value, 'c.value',c.value)
continent_update(w.value)
out.clear_output()
df = filter_dataframe(w.value, None)
with out:
display(df.explore(df.columns[0], cmap="Blues"))
def dropdown_eventhandler2(change):
#continent_update(w.value)
out.clear_output()
df = filter_dataframe(w.value, c.value)
with out:
display(df.explore(df.columns[1], cmap="Blues"))
w.observe(dropdown_eventhandler1, names='value')
c.observe(dropdown_eventhandler2, names='value')
display(w, c)
with out:
display(df.explore(df.columns[0], cmap="Blues", legend=False))
out