回调子集几何数据 - dash Plotly

JPA*_*888 6 python callback plotly choropleth plotly-dash

我希望包含一个带有回调函数的下拉栏,允许用户在较小的区域内显示特定的点。最初,我想使用所有点几何数据作为默认值。然后,我的目标是包含一个下拉栏和回调函数,该函数从该主 df 返回较小的子集。这是通过合并特定多边形区域内的点数据来完成的。

使用下面的方法,默认 df 被标记为gdf_all。这包含一个大区域的点数据。较小的多边形文件是gdf_poly. 其中包括非洲和欧洲大陆。它们在函数中使用,仅在点数据在多边形形状内相交时返回点数据。

我已经对下面的输出进行了硬编码。1) 使用gdf_all2) 使用非洲大陆的子集。

理想情况下,下拉栏将用于输入要在图中可视化的所需点数据。

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)
Run Code Online (Sandbox Code Playgroud)

输出1:

在此输入图像描述

输出2:

在此输入图像描述

Der*_*k O 2

我认为主要任务是转换update_dataset为回调函数,该函数将下拉选择作为输入,并输出新更新的散点图框和条形图。为此,您需要为这两个数字提供一个id参数。dcc.Graph然后在回调中,您可以根据下拉选择重新创建散点图框和条形图。

\n

另外,我不确定您的用例,但为了本示例的目的,我修改了您的merge_withinboundary函数以执行inner join而不是左连接(使用您提供的示例数据,如果您执行左连接,您将总是以 if 这是\xe2\x80\x93gdf_all的第一个参数结束,因为和都完全包含在) 中。然而,我将把这个决定留给你 \xe2\x80\x93 也许左连接就是你想要的实际数据集。merge_withinboundaryAfr_gdf_areaEur_gdf_areagdf_all

\n

出于演示目的,我还设置zoom = 0为默认值,因此当用户gdf_all从下拉列表中选择时,所有点都是可见的。

\n
import geopandas as gpd\nimport plotly.express as px\nimport dash\nfrom dash import dcc, html, Input, Output\nimport dash_bootstrap_components as dbc\n\n# point data\ngdf_all = gpd.read_file(gpd.datasets.get_path("naturalearth_cities"))\n\n# polygon data\ngdf_poly = gpd.read_file(gpd.datasets.get_path("naturalearth_lowres"))\ngdf_poly = gdf_poly.drop(\'name\', axis = 1)\n\ngdf_all[\'LON\'] = gdf_all[\'geometry\'].x\ngdf_all[\'LAT\'] = gdf_all[\'geometry\'].y\n\n# subset African continent\nAfr_gdf_area = gdf_poly[gdf_poly[\'continent\'] == \'Africa\'].reset_index(drop = True)\n\n# subset European continent\nEur_gdf_area = gdf_poly[gdf_poly[\'continent\'] == \'Europe\'].reset_index(drop = True)\n\n# function to merge point data within selected polygon area\ndef merge_withinboundary(gdf1, gdf2):\n\n    # spatial join data within larger boundary\n    gdf_out = gpd.sjoin(gdf1, gdf2, predicate = \'within\', how = \'inner\').reset_index(drop = True)\n\n    return gdf_out\n\ngdf_Africa = merge_withinboundary(gdf_all, Afr_gdf_area)\ngdf_Europe = merge_withinboundary(gdf_all, Eur_gdf_area)\n\n\nexternal_stylesheets = [dbc.themes.SPACELAB, dbc.icons.BOOTSTRAP]\n\napp = dash.Dash(__name__, external_stylesheets = external_stylesheets)\n\n# function to return selected df for plotting\n@app.callback(Output(\'scatter-mapbox\', \'figure\'),\n              Output(\'bar\', \'figure\'),\n              Input(\'data\', \'value\'),\n              prevent_initial_call=True)\n# function to return df using smaller areas\ndef update_dataset(dropdown_selection):\n    if dropdown_selection == \'gdf_Africa\':\n        gdf = gdf_Africa\n        zoom = 2\n\n    elif dropdown_selection == \'gdf_Europe\':\n        gdf = gdf_Europe\n        zoom = 2\n\n    else:\n        gdf = gdf_all\n        zoom = 0\n\n    scatter_subset = px.scatter_mapbox(data_frame = gdf, \n        lat = \'LAT\', \n        lon = \'LON\',\n        zoom = zoom,\n        mapbox_style = \'carto-positron\', \n        )\n    count = gdf[\'name\'].value_counts()\n\n    bar_subset = px.bar(x = count.index, \n                y = count.values, \n                color = count.index, \n                ) \n    return scatter_subset, bar_subset\n\n\nnav_bar =  html.Div([\n     html.P("area-dropdown:"),\n     dcc.Dropdown(\n       id=\'data\', \n       value=\'data\', \n       options=[{\'value\': \'gdf_all\', \'label\': \'gdf_all\'},\n            {\'value\': \'gdf_Africa\', \'label\': \'gdf_Africa\'},\n            {\'value\': \'gdf_Europe\', \'label\': \'gdf_Europe\'}\n            ],\n       clearable=False\n  ),\n])\n\n# output 1\ndf = gdf_all\n\n# output 2\n#df = gdf_Africa\n\nscatter = px.scatter_mapbox(data_frame = df, \n                                   lat = \'LAT\', \n                                   lon = \'LON\',\n                                   zoom = 0,\n                                   mapbox_style = \'carto-positron\', \n                                   )\n\n\ncount = df[\'name\'].value_counts()\n\nbar = px.bar(x = count.index, \n              y = count.values, \n              color = count.index, \n              )\n\napp.layout = dbc.Container([\n    dbc.Row([\n        dbc.Col(html.Div(nav_bar), width=2),\n        dbc.Col([\n            dbc.Row([\n                dbc.Col(dcc.Graph(figure = scatter, id = \'scatter-mapbox\'))\n            ]),\n            dbc.Row([\n                dbc.Col(dcc.Graph(figure = bar, id = \'bar\'))\n            ]),\n        ], width=5),\n        dbc.Col([\n        ], width=5),\n    ])\n], fluid=True)\n\n\nif __name__ == \'__main__\':\n    app.run_server(debug=True, port = 8051)\n
Run Code Online (Sandbox Code Playgroud)\n

在此输入图像描述

\n