使用OSMnx从XML文件创建图时遇AttributeError与TypeError求助
问题:用OSMnx加载过滤后的OSM数据构建城市道路图报错
你需要构建弗留利-威尼斯朱利亚地区的城市道路图:节点为人口>1000的城市,边为主次三级道路(权重为道路长度)。操作流程如下:
- 从OpenStreetMap下载对应区域数据
- 用
osmfilter过滤数据,执行命令:
osmfilter file.osm --keep-nodes="place=* and population>1000 " --keep-ways="highway=primary =secondary =tertiary" --drop-relations --keep= -o=new.osm
- 用OSMnx加载过滤后的数据时触发错误,执行代码:
import osmnx as ox G = ox.graph.graph_from_xml('new.osm', simplify=True)
错误栈信息:
--------------------------------------------------------------------------- AttributeError Traceback (most recent call last) AttributeError: 'float' object has no attribute 'deg2rad' The above exception was the direct cause of the following exception: TypeError Traceback (most recent call last) <ipython-input-2-75f455d1bcf4> in <module> ----> 1 G = ox.graph.graph_from_xml('new.osm', simplify=True) ~/.local/lib/python3.8/site-packages/osmnx/graph.py in graph_from_xml(filepath, bidirectional, simplify, retain_all) 516 517 # create graph using this response JSON --> 518 G = _create_graph(response_jsons, bidirectional=bidirectional, retain_all=retain_all) 519 520 # simplify the graph topology as the last step ~/.local/lib/python3.8/site-packages/osmnx/graph.py in _create_graph(response_jsons, retain_all, bidirectional) 585 # add length (great-circle distance between nodes) attribute to each edge 586 if len(G.edges) > 0: --> 587 G = distance.add_edge_lengths(G) 588 589 return G ~/.local/lib/python3.8/site-packages/osmnx/distance.py in add_edge_lengths(G, precision, edges) 152 153 # calculate great circle distances, round, and fill nulls with zeros --> 154 dists = great_circle_vec(c[:, 0], c[:, 1], c[:, 2], c[:, 3]).round(precision) 155 dists[np.isnan(dists)] = 0 156 nx.set_edge_attributes(G, values=dict(zip(uvk, dists)), name="length") ~/.local/lib/python3.8/site-packages/osmnx/distance.py in great_circle_vec(lat1, lng1, lat2, lng2, earth_radius) 58 earth_radius 59 """ --> 60 y1 = np.deg2rad(lat1) 61 y2 = np.deg2rad(lat2) 62 dy = y2 - y1 TypeError: loop of ufunc does not support argument 0 of type float which has no callable deg2rad method
错误原因
核心问题是手动过滤OSM数据时破坏了道路的拓扑完整性:
- 你的
osmfilter命令只保留了place=* and population>1000的城市节点,但道路(ways)依赖的中间节点(非城市节点)被完全过滤。 - 当OSMnx尝试构建图时,道路的起点/终点可能指向不存在的节点,或剩余节点的经纬度字段缺失/格式异常,导致
np.deg2rad处理时遇到无效的float对象(如NaN或非数值类型)。
解决方案与更优构建方案
1. 修复手动过滤流程
调整osmfilter命令,保留道路关联的所有节点(不仅是城市节点):
osmfilter file.osm --keep-nodes="place=* and population>1000 OR (highway=*)" --keep-ways="highway=primary =secondary =tertiary" --drop-relations -o=new.osm
解释:保留城市节点的同时,保留所有与道路关联的节点,确保道路的拓扑连接性。
2. 推荐:OSMnx原生方案(无需手动下载过滤)
直接用OSMnx内置功能获取指定区域、道路类型的图,再过滤城市节点,流程更简洁且不易出错:
import osmnx as ox # 定义目标区域 region = "Friuli-Venezia Giulia, Italy" # 获取主次三级道路的完整路网 G = ox.graph_from_place(region, custom_filter='["highway"~"primary|secondary|tertiary"]', network_type="drive") # 过滤出人口>1000的城市节点 city_nodes = [n for n, data in G.nodes(data=True) if 'population' in data and int(data['population']) > 1000] # 构建仅包含城市节点的子图(保留节点间的道路) G_city_graph = G.subgraph(city_nodes).copy() # 确保边长度属性存在(OSMnx默认已添加,若缺失可手动执行) G_city_graph = ox.distance.add_edge_lengths(G_city_graph)
该方案优势:
- 自动处理OSM数据的下载、校验和拓扑构建,避免手动过滤的疏漏
- 内置图简化、坐标校验功能,降低出错概率
- 支持直接通过地名定位区域,无需手动寻找下载链接
3. 调试辅助
若仍遇坐标错误,可检查无效节点:
# 找出无有效经纬度的节点 invalid_nodes = [n for n, data in G.nodes(data=True) if 'y' not in data or 'x' not in data or not isinstance(data['y'], float)] print(f"无效节点数量:{len(invalid_nodes)}")
删除无效节点后再重新构建图即可。
内容的提问来源于stack exchange,提问作者Hyppolite
相关产品推荐
相关产品推荐

