首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >使用python dash-leaflet高效过滤GeoJSON组件

使用python dash-leaflet高效过滤GeoJSON组件
EN

Stack Overflow用户
提问于 2021-01-11 21:56:29
回答 1查看 787关注 0票数 4

我正在使用Dash Leaflet地图组件dash-leaflet进行交互式地图可视化。

我的目标是根据破折号组件(例如dcc.Slider)的值来过滤大型GeoJSON组件(dl.GeoJSON)。

我目前的方法如下:

代码语言:javascript
复制
import random
import dash
import dash_html_components as html
import dash_leaflet as dl
import dash_leaflet.express as dlx
import dash_core_components as dcc
from dash.dependencies import Input, Output

# Create some markers.
points = [dict(lat=55.5 + random.random(), lon=9.5 + random.random(), value=random.random()*100) for i in range(100)]
data = dlx.dicts_to_geojson(points)

app = dash.Dash()
app.layout = html.Div([
    dl.Map([
        dl.TileLayer(),
        dl.GeoJSON(id="data-id", data=data)
        ], center=(56, 10), zoom=8, style={'height': '50vh'}),
    html.Div([
        html.H5('Filtering'),
        dcc.Slider(id='my-slider', min=0, max=100, step=1, value=100),
        html.Div(id='slider-output-container')
        ], style={'width': '30%'}),
    ])

@app.callback(
    Output('slider-output-container', 'children'),
    Output('data-id', 'data'),
    [Input('my-slider', 'value')])
def update_output(value):
    points_new = [p for p in points if p['value'] <= value]
    data_new = dlx.dicts_to_geojson(points_new)
    return 'You have selected value "{}"'.format(value), data_new

if __name__ == '__main__':
    app.run_server()

在此示例中,使用破折号组件“my- GeoJSON”的值筛选数据组件" data -id“的数据对象,方法是根据输入值筛选点列表并返回使用dlx.dicts_to_geojson函数创建的新geoJSON对象:

代码语言:javascript
复制
points_new = [p for p in points if p['value'] <= value]
data_new = dlx.dicts_to_geojson(points_new)

这是过滤geoJSON对象的正确方式吗?

我可以想象,有更好的方法可以使用GeoJSON组件的options-feature和javascript函数在客户端定义这样的过滤器函数,但我不知道如何定义。

我很感谢我能得到的任何建议/代码示例。

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2021-01-12 04:25:35

虽然可以在Python中过滤数据,但根据数据大小的不同,可能会引入大量的网络开销(每次过滤器更改时,数据都会从服务器传输到客户端)。如果你在客户端进行过滤,你只需要传输一次数据,即性能差异可能是巨大的。

客户端过滤可以通过根据the documentation添加具有过滤功能的JavaScript资产(即,放置在assets文件夹中的.js文件)来实现,

代码语言:javascript
复制
window.myNamespace = Object.assign({}, window.myNamespace, {  
    mySubNamespace: {  
        filter_features: function(feature, context) {
            // code should return true if feature is included, otherwise false
            const value = context.props.hideout['value']
            ...
        }  
    }  
});

要应用过滤,请将filter函数的函数句柄传递给GeoJSON组件,

代码语言:javascript
复制
import dash_leaflet as dl
from dash_extensions.javascript import Namespace
...
ns = Namespace("myNamespace ", "mySubNamespace")
dl.GeoJSON(id="geojson", options=dict(filter=ns("filter_features"), ...)

最后,通过使过滤器依赖于hideout属性(如上面的示例代码所示),您可以通过回调更新此属性来实现交互性。

代码语言:javascript
复制
@app.callback(Output("geojson", "hideout"), ...)
def update(...):
    ...
    return {"value": value}

编辑:根据评论中的请求,这里是一个小型的自包含示例,演示了仅使用客户端逻辑的交互式geojson过滤。

代码语言:javascript
复制
import dash_html_components as html
import dash_leaflet as dl
import dash_core_components as dcc
import dash_leaflet.express as dlx
from dash import Dash
from dash.dependencies import Output, Input
from dash_extensions.javascript import assign

# A few cities in Denmark.
cities = [dict(name="Aalborg", lat=57.0268172, lon=9.837735),
          dict(name="Aarhus", lat=56.1780842, lon=10.1119354),
          dict(name="Copenhagen", lat=55.6712474, lon=12.5237848)]
# Create drop down options.
dd_options = [dict(value=c["name"], label=c["name"]) for c in cities]
dd_defaults = [o["value"] for o in dd_options]
# Generate geojson with a maker for each city and name as tooltip.
geojson = dlx.dicts_to_geojson([{**c, **dict(tooltip=c['name'])} for c in cities])
# Create javascript function that filters on feature name.
geojson_filter = assign("function(feature, context){return context.props.hideout.includes(feature.properties.name);}")
# Create example app.
app = Dash()
app.layout = html.Div([
    dl.Map(children=[
        dl.TileLayer(),
        dl.GeoJSON(data=geojson, options=dict(filter=geojson_filter), hideout=dd_defaults, id="geojson")
    ], style={'width': '100%', 'height': '50vh', 'margin': "auto", "display": "block"}, id="map"),
    dcc.Dropdown(id="dd", value=dd_defaults, options=dd_options, clearable=False, multi=True)
])
# Link drop down to geojson hideout prop (could also be done with a normal callback).
app.clientside_callback("function(x){return x;}", Output("geojson", "hideout"), Input("dd", "value"))

if __name__ == '__main__':
    app.run_server()

请注意,它需要dash-extensions==0.0.55

票数 3
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/65668208

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档