
做GIS的人都知道传统空间分析是在点线面上做文章做图神经网络的人都知道GNN吃的是图——节点带特征、边带权重。中间这一步把「空间数据」翻译成「图结构」长期是个手工活先把POI落节点再算两两距离定边再把路网叠进去最后导出成PyG的Tensor。City2Graph把这一步封成了几行函数调用。本文拿济南趵突泉周边实测1200个POI、4529条道路、8803栋建筑跑通固定半径图、Waxman随机图、城市形态图、异构图转PyG全流程。目录一、City2Graph是什么1.1它解决什么问题1.2三个核心函数二、数据准备趵突泉周边的三栖数据2.1三类数据清单2.2数据获取的细节三、fixed_radiusvsWaxman四种连边方式对比3.1四种图结构对比3.1.1 对比数据3.1.3 程序3.1.3 出图对比3.2两个值得注意的点3.3四种图分别适合什么场景四、morphological 500m城市形态学图4.1什么是morphological图4.2从图上读出的五个结论4.3空间结构诊断与改造建议五、一行转PyGHeteroDataGIS到GNN的最后一公里5.1 HeteroData长什么样5.2转完之后能跑什么分析六、什么时候用、什么时候别用一、City2Graph是什么1.1它解决什么问题City2Graph是利物浦大学YutaSato团队2026年开源的GeoAI图库BSD-3-ClauseGitHub约1.9kstar对应论文发表在Computers,EnvironmentandUrbanSystems。它解决一件事把城市里多源的空间数据POI点、道路线、建筑面、GTFS公交线路、共享单车OD统一转成图结构并且在三种数据格式之间互转——GeoPandasGeoDataFrameGIS世界、NetworkX图算法世界、PyGHeteroData深度学习世界。1.2三个核心函数关键函数三个fixed_radius_graph固定半径连边、waxman_graph随机几何图、morphological_graph城市形态学图。加上gdf_to_pyg一行转PyG。二、数据准备趵突泉周边的三栖数据2.1三类数据清单测试范围选济南泉城广场周边1.2公里实际POI集中在趵突泉片区。三类数据全部国内可获取数据来源数量用途POI兴趣点高德1200个6类×200图节点道路网OvertureMaps4529条segmentsnetwork距离/morphological障碍物建筑轮廓OvertureMaps8803栋morphological图节点表1趵突泉周边实测数据清单2.2数据获取的细节POI用高德个人key按餐饮、购物、风景名胜、医疗、住宿、生活服务六类各拉200条数据坐标系一致需要转WGS-843、道路和建筑都来自OvertureMaps2024开放数据集city2graph的load_overture_data函数直接按bbox拉parquet。三、fixed_radiusvsWaxman四种连边方式对比3.1四种图结构对比3.1.1 对比数据同样1200个POI换四种连边规则图结构差异巨大。图类型距离口径节点边数图特征fixed_radius100m欧氏120022,521硬阈值边数最多waxmaneuclidean欧氏随机120014,808中密度waxmanmanhattan曼哈顿120010,886网格距离边较少waxmannetwork沿道路12005,586真实距离最长边最少表2四种图结构对比3.1.3 核心程序fixed_radius100mfr_nodes, fr_edges c2g.fixed_radius_graph(poi_m, radius100, distance_metriceuclidean)waxmaneuclideanw_eu_nodes, w_eu_edges c2g.waxman_graph(poi_m, beta0.5, r0100, distance_metriceuclidean, seed42)waxmanmanhattanw_ma_nodes, w_ma_edges c2g.waxman_graph(poi_m, beta0.5, r0100, distance_metricmanhattan, seed42)waxmannetworkw_nt_nodes, w_nt_edges c2g.waxman_graph( poi_m, beta0.5, r0100, distance_metricnetwork, network_gdfedges_m, network_weightlength, seed42 )3.1.3 出图对比固定半径红、欧氏Waxman橙、曼哈顿Waxman黄、沿道路Waxman蓝图1四种连边方式对比3.2两个值得注意的点两个值得注意的点第一曼哈顿距离的边数比欧氏少近30%。原因是曼哈顿距离对同样半径「实际覆盖范围」是菱形而非圆形在网格城市里邻居数天然偏少。第二沿道路连边后边数最少5586只有固定半径图的四分之一。原因是沿道路最短路径距离天然比直线距离长——两个POI直线200m沿路可能要走400mWaxman概率P0.5·exp(-d/100)下d越大连边概率越低。这就是「直线距离」和「步行可达性」的本质差异。3.3四种图分别适合什么场景四种图分别适合什么场景图类型边数适合场景不适合fixed_radius22,521商圈覆盖、学区划片、15分钟生活圈等政策硬分析真实步行可达性评估waxmaneuclidean14,808GNN冷启动、POI相似度建模、快速实验有明显河流/铁路阻隔的城市waxmanmanhattan10,886老城区网格街区模拟、步行距离近似地形起伏、弯道多的城市waxmannetwork5,586商业选址、外卖配送范围、真实步行可达性万级以上节点all-pairs最短路耗时剧增表3四种图的适用场景一句话做商业分析用network做快速实验用euclidean做政策硬分析用fixed_radius。四、morphological500m城市形态学图4.1什么是morphological图前三张图都是POI自己和自己连边。morphological_graph不一样——它用建筑面和道路段当「障碍物」把城市空间切成两类节点place建筑围合出来的开放空间和movement街道本身再连三种边place相邻touched_to、街道连通connected_to、空间面向街道faced_to。morphological代码nodes_dict, edges_dict c2g.morphological_graph( buildings_gdfbuildings, segments_gdfsegments_m, center_pointcenter, distance500, keep_buildingsTrue, keep_segmentsTrue, )彩色点place灰线道路图2趵突泉周边morphological图500m半径内跑出243个place、66条movement、共1037条边。这不是POI图是「城市空间结构」图——它回答的问题是这个商圈有几个开放空间、哪几条街把它们串起来。TOP10彩色标注灰色孤立place115个图3院落群空间分布4.2从图上读出的五个结论从数据可以看出五个结论1核心区主要院落群挤在不到1平方公里内空间非常密集。2最大群22个place在核心区西北边缘不在正中心。空间重心偏西东边反而是小群。3南边有一整群独立院落9个place和核心区隔了约500m空白带没有任何连通边——这是图上最明显的断裂带。4243个place里有115个是孤立点灰色占47%。近一半开放空间没有邻居空间是碎的。5西边群1/2/3/8规模大东边群4/5/6/10规模中等没有一个群是压倒性主群——是多中心结构。4.3空间结构诊断与改造建议空间结构诊断问题1近一半空间是孤立点。115个place没有任何touched_to邻居说明开放空间被道路/建筑切割得很碎没有形成连续的步行界面。问题2南边断裂带。核心区和南边独立群之间有500m宽的空白带没有连通——两边的人流走不到一起。问题3最大群在边缘不在中心。22个place的最大群在西北边缘说明核心区正中心的空间连通性反而不如边缘。改造建议图上能直接指出来的建议1打通西北边缘的最大群群122place和中部群群315place。两个群隔得最近但没有连通边打通后能合并成37place的超级院落群。建议2在南边断裂带核心区和独立群之间500m空白加一条步行连通通道把南北两边的空间串起来。建议3把115个孤立点里位置相邻的几个先连起来降低孤立点比例——孤立点越多人流越散。五、一行转PyGHeteroDataGIS到GNN的最后一公里5.1HeteroData长什么样所有图最终要落到PyG上训练。City2Graph一行gdf_to_pyg直接出HeteroData我们把POI1200个和建筑8803栋作为两类节点bridge_nodes用knn5把每个POI连到最近的5栋建筑得到6000条(poi,is_nearby,building)边。gdf_to_pyg输出的HeteroData长这样HeteroData(poi{x[1200,0],pos[1200,2]},building{x[8803,0],pos[8803,2]},(poi,is_nearby,building){edge_index[2,6000]},(building,rev_is_nearby,poi){edge_index[2,6000]})注意两点一是自动生成了反向边rev_is_nearbyGNN训练时双向消息传递不用自己写二是x目前是0维没塞特征把POI类型one-hot、建筑层高/屋顶形状灌进去就是[1200,6]和[8803,3]直接能跑GCN。pyg_to_nx回环也通GeoPandas→NetworkX→PyG三方互转闭环。5.2转完之后能跑什么分析转完HeteroData之后能跑什么分析现在x[1200,0]是空特征灌三类特征进去就能跑GNNPOI类型one-hot6类→[1200,6]、建筑面积/层高→[8803,3]、图结构特征节点度、中心度。三个可直接落地的分析分析图嵌入商圈子群发现。用GraphSAGE把1200个POI降到2维实际跑出来6类POI完全分成了6个独立簇。右图——embedding同时学到了空间位置颜色越黄越北、越紫越南和实际纬度对应。这说明GNN不只是分类还能把「业态」和「空间」两个维度同时编码进二维向量里。转换程序nodes, edges c2g.waxman_graph(poi, beta0.5, r0100, distance_metriceuclidean, seed42)左图按POI类型着色6类完全分开右图按纬度着色颜色渐变和空间位置对应图4 GraphSAGE2D嵌入本次实测跑通了全流程GeoPandas数据→四种图结构→morphological空间分析→PyGHeteroData→GraphSAGE嵌入。从GIS到GNN的最后一公里City2Graph确实把手工活封成了几行函数。六、什么时候用、什么时候别用适合的场景商圈活力分析POI图、步行可达性network距离、城市空间结构morphological、把已有GIS数据快速喂给GNN做选址/分类预测。不适合的场景大区域全国级图——1200个POI已经跑出2.2万边10万节点就是百万边级别内存吃紧需要精确交通阻抗的——network模式用的是道路长度不是真实驾车时间建筑和道路数据国内依赖OvertureMaps小地块可能不全。