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

如何利用Geopandas与Neo4j数据绘制节点间关系图?

解决方案

要绘制节点间的GO关系(道路),你需要先获取每条关系对应的起点、终点坐标,再将这些坐标转换为地理线段,最后叠加到已有的节点地图上。具体步骤如下:

1. 修改Cypher查询,获取关系的完整坐标信息

原来的关系查询仅返回节点ID,需要补充查询起点和终点的经纬度,才能生成可绘制的线段:

MATCH (n1)-[:GO]-(n2) 
RETURN n1.id AS start_id, 
       n1.latitude AS start_lat, 
       n1.longitude AS start_lon, 
       n2.id AS end_id, 
       n2.latitude AS end_lat, 
       n2.longitude AS end_lon

2. 处理关系数据,转换为地理线段

使用shapely的LineString类,将每条关系的起点、终点坐标组合成线段几何对象,再转换为GeoDataFrame格式。

3. 叠加绘制道路线段

在已有的节点地图轴上,添加道路线段的绘制,注意调整绘制顺序保证节点可见。

完整代码示例

from py2neo import Graph
import pandas as pd
import geopandas
import matplotlib.pyplot as plt
from shapely.geometry import LineString  # 新增导入,用于创建线段

port = "7687"
user = "****"
pswd = "*****"    

try:
    graph = Graph('bolt://localhost:'+port, auth=(user, pswd))
    print('SUCCESS: Connected to the Neo4j Database.')
except Exception as e:
    print('ERROR: Could not connect to the Neo4j Database. See console for details.')
    raise SystemExit(e)    

# 1. 查询节点数据并处理
df_nodes = pd.DataFrame(graph.run("MATCH (n:Road) RETURN n.id, n.latitude, n.longitude").to_table(), columns=['ID','Latitude','Longitude']) 
# 将字符串坐标转为数值类型
df_nodes['Latitude'] = df_nodes['Latitude'].astype(float)
df_nodes['Longitude'] = df_nodes['Longitude'].astype(float)
gdf_nodes = geopandas.GeoDataFrame(df_nodes, geometry=geopandas.points_from_xy(df_nodes.Longitude, df_nodes.Latitude))    

# 2. 查询关系数据并转换为线段
df_roads = pd.DataFrame(
    graph.run("""
        MATCH (n1)-[:GO]-(n2) 
        RETURN n1.id AS start_id, 
               n1.latitude AS start_lat, 
               n1.longitude AS start_lon, 
               n2.id AS end_id, 
               n2.latitude AS end_lat, 
               n2.longitude AS end_lon
    """).to_table(),
    columns=['start_id', 'start_lat', 'start_lon', 'end_id', 'end_lat', 'end_lon']
)
# 转换坐标为数值类型
df_roads[['start_lat', 'start_lon', 'end_lat', 'end_lon']] = df_roads[['start_lat', 'start_lon', 'end_lat', 'end_lon']].astype(float)

# 创建线段几何列
gdf_roads = geopandas.GeoDataFrame(
    df_roads,
    geometry=[LineString([(row['start_lon'], row['start_lat']), (row['end_lon'], row['end_lat'])]) 
              for _, row in df_roads.iterrows()]
)

# 3. 绘制完整地图:底图 → 道路 → 节点
world = geopandas.read_file(geopandas.datasets.get_path('naturalearth_lowres'))
ax = world[world.continent == 'North America'].plot(color='white', edgecolor='black')    

# 先画道路,再画节点(确保节点不被道路遮挡)
gdf_roads.plot(ax=ax, color='gray', linewidth=1)
gdf_nodes.plot(ax=ax, color='red', markersize=5)

plt.show()

关键说明

  • 坐标类型转换:从Neo4j返回的经纬度默认是字符串,必须转换为float类型才能创建有效的地理对象。
  • 绘制顺序:先绘制道路再绘制节点,避免节点被道路遮挡,保证节点的可见性。
  • 线段创建:通过LineString将每对起点终点的经纬度组合成线段,这是GeoPandas识别并绘制道路的核心步骤。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.03 16:01:01