如何使用Geopandas和Neo4j数据绘制点之间的关系?

5us2dqdw  于 2023-03-12  发布在  其他
关注(0)|答案(1)|浏览(157)

我有一个简单的Neo4J道路数据库,城市(节点)有纬度、经度、id和关系为GO的道路。
例如:MATCH (city) RETURN (city) LIMIT 5

{"latitude":"41.974556","id":"0","longitude":"-121.904167"} 
    {"latitude":"41.974766","id":"1","longitude":"-121.902153"} 
    {"latitude":"41.988075","id":"2","longitude":"-121.896790"} 
    {"latitude":"41.998032","id":"3","longitude":"-121.889603"} 
    {"latitude":"42.008739","id":"4","longitude":"-121.886681"}

MATCH (n1)-\[r\]-(n2) RETURN "GO", n1.id, n2.id LIMIT 4
| “出发”|“n1.id“|“n2.id“|
| - ------|- ------|- ------|
| “出发”|“零”|“1”|
| “出发”|“零”|“三”|
| “出发”|“1”|“零”|
| “出发”|“1”|“二”|
使用下面的代码,我可以创建一个包含Map上节点的图:

from py2neo import Graph
    import pandas as pd
    import geopandas
    import matplotlib.pyplot as plt    

    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)    

    df = pd.DataFrame(graph.run("MATCH (n:Road) RETURN n.id, n.latitude, n.longitude").to_table(),columns=['ID','Latitude','Longitude']) 
    df.head()
    gdf = geopandas.GeoDataFrame(df, geometry=geopandas.points_from_xy(df.Longitude, df.Latitude))    

    world = geopandas.read_file(geopandas.datasets.get_path('naturalearth_lowres'))
    ax = world[world.continent == 'North America'].plot(color='white', edgecolor='black')    

    gdf.plot(ax=ax, color='red')
    plt.show()

我不知道如何绘制节点之间的关系。有什么建议吗?谢谢。

3npbholx

3npbholx1#

在使用GeoPandas.GeoDataFrame.plot()绘图的示例中,GeoDataFrame的几何形状是点数据(存储在Neo4j中的Road节点的纬度/经度坐标)。要使用此方法绘制关系,还需要连接道路节点(交叉点)的线的几何形状。
我刚刚用机场和航班数据做了类似的练习,也许你可以适应你的数据。
第一,在用于获取稍后将加载到GeoDataFrame中的数据的Cypher查询中,我使用模式(:Airport)-[:FLIGHT_TO]->(:Airport)查找每个航班,因为我希望GeoDataFrame中的每一行都是两个机场之间的飞行路线。我还计算了每个机场的加权度中心度,以便我们可以相对于图中的中心度设置节点大小的样式。我们还为机场位置生成了WKT(点)以及梯段(线串)。

AIRPORT_QUERY = """
  MATCH (origin:Airport)-[f:FLIGHT_TO]->(dest:Airport)
  CALL {
   WITH origin
   MATCH (origin)-[f:FLIGHT_TO]-()
   RETURN sum(f.num_flights) AS origin_centrality
  }
  CALL {
   WITH dest
   MATCH (dest)-[f:FLIGHT_TO]-()
   RETURN sum(f.num_flights) AS dest_centrality
  }
  RETURN {
    origin_wkt: "POINT (" + origin.location.longitude + " " + origin.location.latitude + ")",
    origin_iata: origin.iata, 
    origin_city: origin.city, 
    origin_centrality: origin_centrality, 
    dest_centrality: dest_centrality,
    dest_wkt: "POINT (" + dest.location.longitude + " " + dest.location.latitude + ")",
    dest_iata: dest.iata, 
    dest_city: dest.city, 
    length: f.length,
    num_flights: f.num_flights,
    geometry: "LINESTRING (" + origin.location.longitude + " " + origin.location.latitude + "," + dest.location.longitude + " " + dest.location.latitude + ")"
    
    } 
  AS airport
"""

Neo4j Python驱动程序有一个to_df()方法,我们可以使用它将Cypher查询的结果集转换为Pandas数据框。然后,当我们创建Geopandas GeoDataFrame时,我们可以将Cypher语句返回的WKT解析为Shapely几何图形。

def get_airport(tx):
    results = tx.run(AIRPORT_QUERY)
    df = results.to_df(expand=True)
    df.columns=['origin_city','origin_wkt', 'dest_city', 'dest_wkt', 'origin_centrality', 'length', 'origin_iata', 'geometry','num_flights', 'dest_centrality', 'dest_iata']
    df['geometry'] = geopandas.GeoSeries.from_wkt(df['geometry'])
    df['origin_wkt'] = geopandas.GeoSeries.from_wkt(df['origin_wkt'])
    df['dest_wkt'] = geopandas.GeoSeries.from_wkt(df['dest_wkt'])
    gdf = geopandas.GeoDataFrame(df, geometry='geometry')
    return gdf

现在我们可以绘制航班了,我们可以使用机场的加权度中心列动态设置机场的标记大小。

world = geopandas.read_file(geopandas.datasets.get_path('naturalearth_lowres'))

base = world[world.name == 'United States of America'].plot(color='white', edgecolor='black')

flights_gdf = flights_gdf.set_geometry("origin_wkt")
flights_gdf.plot(ax=base, markersize='origin_centrality')

flights_gdf = flights_gdf.set_geometry("geometry")
flights_gdf.plot(ax=base, markersize=0.1, linewidth=0.01)

plt.show()

希望能有所帮助。

相关问题