You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

OSMNX中custom_filter与df.apply筛选自行车道结果差异问题

问题:OSMnx custom_filter筛选自行车道结果异常

我在统计德国卡尔斯鲁厄市的自行车道总长度时,发现两种方法结果差异极大:

  • 方法一用custom_filter='["highway"~"cycleway"]'筛选,得到约23公里
  • 方法二先获取全部自行车网络,再筛选highway字段包含"cycleway"的条目,得到约109公里

手动核对后发现:方法一仅统计了带多个标签(如['cycleway', 'service'])的路段,漏掉了仅标记为"cycleway"的路段;方法二则两种都统计到了。想知道方法一中custom_filter的使用错误在哪里。

两种方法代码

方法一

city = "Karlsruhe, Germany"
graph = ox.graph_from_place(city, network_type="bike", custom_filter='["highway"~"cycleway"]')
cycleways = ox.graph_to_gdfs(graph, nodes=False, edges=True)
length = cycleways["length"].sum()/1000
print(length)

方法二

city = "Karlsruhe, Germany"
graph = ox.graph_from_place(city, network_type="bike")
cycleways = ox.graph_to_gdfs(graph, nodes=False, edges=True)
contains_cycleway = cycleways["highway"].apply(lambda value: "cycleway" in str(value))
cycleways = cycleways[contains_cycleway]
length = cycleways["length"].sum()/1000
print(length)

原因与修正方案

核心错误

  1. custom_filter会覆盖network_type的默认规则:当你同时指定network_type="bike"和custom_filter时,OSMnx会忽略自行车网络的默认过滤条件(比如排除bicycle=no的道路),仅用你写的custom_filter筛选。而方法二中,network_type="bike"会自动过滤掉不允许自行车通行的道路,之后你再筛选highway包含cycleway的条目,范围更准确。
  2. 你的custom_filter缺少通行权限过滤:仅用["highway"~"cycleway"]会获取所有highway标签含cycleway的道路,但其中可能包含bicycle=no的路段,而方法二中的network_type="bike"已经排除了这些。你手动核对发现方法一没统计仅标记为cycleway的路段,大概率是因为这类路段都符合自行车通行规则,但你的custom_filter没结合network_type的默认过滤,导致Overpass返回的结果不全。

修正后的custom_filter写法

如果你想通过custom_filter实现和方法二完全一致的效果,需要把自行车网络的默认过滤条件和自定义筛选结合起来:

写法一:严格匹配方法二的逻辑

city = "Karlsruhe, Germany"
# 结合自行车网络默认过滤规则 + 仅保留highway含cycleway的道路
custom_filter = '["highway"~"cycleway|path|track|footway|bridleway|steps|pedestrian|living_street|service|unclassified|residential|tertiary|secondary|primary|trunk"]["bicycle"!~"no"]["highway"~"cycleway"]'
graph = ox.graph_from_place(city, custom_filter=custom_filter)
cycleways = ox.graph_to_gdfs(graph, nodes=False, edges=True)
length = cycleways["length"].sum()/1000
print(length)

写法二:更简洁的目标匹配

如果你只需要highway含cycleway且允许自行车通行的道路,直接写:

custom_filter = '["highway"~"cycleway"]["bicycle"!~"no"]'

这样就能同时匹配:

  • 仅标记为"cycleway"的单一标签道路
  • 含"cycleway"的多标签道路(如['cycleway', 'service'])
  • 自动排除bicycle=no的无效路段

关键注意点

  • Overpass QL语法中:
    • ["highway"="cycleway"]:仅匹配highway值完全等于cycleway的道路(包括单一标签和仅含cycleway的多标签数组)
    • ["highway"~"cycleway"]:匹配highway值(或多标签数组中的元素)包含cycleway的道路(比如cycleway_link也会被匹配,若不需要可调整正则为["highway"~"^cycleway$"])
  • 只要指定custom_filter,network_type的默认规则就会失效,需要手动添加必要的过滤条件(如["bicycle"!~"no"])。

内容的提问来源于stack exchange,提问作者FesterShinetop

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.14 11:07:03