我希望包含一个下拉栏和回调函数,允许用户在较小的区域内显示特定的点。最初,我希望使用所有的点几何数据作为默认值。然后,我的目标是包含一个下拉栏和回调函数,从这个主df返回较小的子集。这是通过合并特定多边形区域内的点数据来实现的。
使用下面的,默认df标记为gdf_all
。它包含大区域的点数据。较小的多边形文件是gdf_poly
的子集。包括非洲和欧洲大陆。这些文件用于函数中,仅当点数据与多边形形状相交时才返回点数据。
我已经硬编码了下面的输出。1)使用gdf_all
和2)使用来自非洲大陆的子集。
理想情况下,下拉栏将用于输入所需的点数据,以便在图中显示。
import geopandas as gpd
import plotly.express as px
import dash
from dash import dcc
from dash import html
import dash_bootstrap_components as dbc
# point data
gdf_all = gpd.read_file(gpd.datasets.get_path("naturalearth_cities"))
# polygon data
gdf_poly = gpd.read_file(gpd.datasets.get_path("naturalearth_lowres"))
gdf_poly = gdf_poly.drop('name', axis = 1)
gdf_all['LON'] = gdf_all['geometry'].x
gdf_all['LAT'] = gdf_all['geometry'].y
# subset African continent
Afr_gdf_area = gdf_poly[gdf_poly['continent'] == 'Africa'].reset_index(drop = True)
# subset European continent
Eur_gdf_area = gdf_poly[gdf_poly['continent'] == 'Europe'].reset_index(drop = True)
# function to merge point data within selected polygon area
def merge_withinboundary(gdf1, gdf2):
# spatial join data within larger boundary
gdf_out = gpd.sjoin(gdf1, gdf2, predicate = 'within', how = 'left').reset_index(drop = True)
return gdf_out
gdf_Africa = merge_withinboundary(gdf_all, Afr_gdf_area)
gdf_Europe = merge_withinboundary(gdf_all, Eur_gdf_area)
external_stylesheets = [dbc.themes.SPACELAB, dbc.icons.BOOTSTRAP]
app = dash.Dash(__name__, external_stylesheets = external_stylesheets)
# function to return selected df for plotting
def update_dataset(df):
if df == 'gdf_Africa':
gdf = gdf_Africa
elif df == 'gdf_Europe':
gdf = gdf_Europe
else:
gdf = gdf_all
return gdf
nav_bar = html.Div([
html.P("area-dropdown:"),
dcc.Dropdown(
id='data',
value='data',
options=[{'value': 'gdf_all', 'label': 'gdf_all'},
{'value': 'gdf_Africa', 'label': 'gdf_Africa'},
{'value': 'gdf_Europe', 'label': 'gdf_Europe'}
],
clearable=False
),
])
# output 1
df = gdf_all
# output 2
#df = gdf_Africa
scatter = px.scatter_mapbox(data_frame = df,
lat = 'LAT',
lon = 'LON',
zoom = 2,
mapbox_style = 'carto-positron',
)
count = df['name'].value_counts()
bar = px.bar(x = count.index,
y = count.values,
color = count.index,
)
app.layout = dbc.Container([
dbc.Row([
dbc.Col(html.Div(nav_bar), width=2),
dbc.Col([
dbc.Row([
dbc.Col(dcc.Graph(figure = scatter))
]),
dbc.Row([
dbc.Col(dcc.Graph(figure = bar))
]),
], width=5),
dbc.Col([
], width=5),
])
], fluid=True)
if __name__ == '__main__':
app.run_server(debug=True, port = 8051)
产出1:
产出2:
2条答案
按热度按时间nc1teljy1#
我有一个部分可行的解决方案,但是需要做很多修改。当你使用
px.choropleth
创建一个地区分布图时,geojson参数必须是(GeoJSON-formatted dict) – Must contain a Polygon feature collection, with IDs, which are references from locations
(来自documentation)--传递geojson = A_gdf_area
是行不通的,因为A_gdf_area
是GeoDataFrame
。此外,geojson文件需要包含位置和颜色的列,以便在区域分布图上使用颜色-我不知道您打算使用哪些列来为Map着色,所以我创建了名为
ids
和vals
的虚拟列,用于提供位置和颜色。由于您正在绘制意大利的区域(而px.choropleth只绘制世界各国或美国各州的边界),因此您需要首先使用从geojson中提取的
lats
和lons
创建一个go.Scattergeo
图形,然后将choropleth数据作为跟踪添加到该图形(此想法的功劳归于plotly论坛上的this answer)。我已经把这个整合到下面的dash应用程序中,唯一的问题是
vals
列对应的颜色似乎没有像我期望的那样呈现在图中--当我弄清楚原因时,我会更新这个答案。enxuqcxy2#
尝试下面的方法。这会修改下拉列表中的选项列表以包含较小数据框的名称。然后,它会创建一个回调函数,该函数从下拉列表中获取所选值,并使用该值过滤主数据框以获得相应的较小数据框。
因此,它添加了三个新的数据框gdf_A、gdf_B和gdf_C,它们是在相应的较小数据框上调用merge_withinboundary的结果。此外,下拉列表中的选项列表被修改为包括名称。希望这能有所帮助!