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

使用OSMnx从XML文件创建图时遇AttributeError与TypeError求助

问题:用OSMnx加载过滤后的OSM数据构建城市道路图报错

你需要构建弗留利-威尼斯朱利亚地区的城市道路图:节点为人口>1000的城市,边为主次三级道路(权重为道路长度)。操作流程如下:

  1. 从OpenStreetMap下载对应区域数据
  2. 用osmfilter过滤数据,执行命令:
osmfilter file.osm --keep-nodes="place=* and population>1000 " --keep-ways="highway=primary =secondary =tertiary" --drop-relations --keep= -o=new.osm 
  1. 用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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.31 12:46:14