注意
前往末尾 下载完整示例代码。
从线集合构建图#
本示例展示了如何使用 GeoPandas、momepy 以及 PySAL(作为备选)从一组地理线(有时称为“线串”)构建图。我们将绘制一些河流和街道,以及由这些线段形成的图。
通常有两种方法从线几何对象创建图对象。让我们以街道网络为例来演示这两种方法。
第一种方法称为原始(primal)方法,其中每个交叉点是一个节点,连接两个交叉点的每个线串段是一条边。
第二种方法称为对偶(dual)方法,其中每条线是一个节点,交叉点拓扑被转换为边。这种方法用于街道网络分析的一个选项是角度分析,其中您的路由通过交叉点处街道段之间的角度进行加权。
我们将使用 GeoPandas 读取空间数据,并使用 momepy 首先生成原始图,然后生成对偶图。此外,我们将使用 PySAL 演示创建原始对偶图的另一种方法。
import geopandas
import matplotlib.pyplot as plt
import momepy
import networkx as nx
from contextily import add_basemap
from libpysal import weights
从 GeoJSON 读取示例河流几何数据。示例数据来源: https://doi.org/10.3390/data5010008 (Nicolas Cadieux)
rivers = geopandas.read_file("rivers.geojson")
构建原始图。momepy 自动保留 GeoDataFrame 中的所有属性,并将其存储为边属性。
G = momepy.gdf_to_nx(rivers, approach="primal")
每个节点由其坐标编码,这使得我们可以在绘图中使用它们。

完成基于图的分析后,我们可以将图转换回 GeoDataFrames。momepy 可以将节点作为点几何对象返回,将边作为原始线几何对象返回,并返回一个 W 对象,该对象是编码原始图的 PySAL 空间权重矩阵,因此我们可以将其与节点 GeoDataFrame 一起使用。
nodes, edges, W = momepy.nx_to_gdf(G, spatial_weights=True)
# Read in example street network from GeoPackage
streets = geopandas.read_file(momepy.datasets.get_path("bubenec"), layer="streets")
# Construct the primal graph
G_primal = momepy.gdf_to_nx(streets, approach="primal")
# Plot
f, ax = plt.subplots(1, 2, figsize=(12, 6), sharex=True, sharey=True)
streets.plot(color="k", ax=ax[0])
for i, facet in enumerate(ax):
facet.set_title(("Streets", "Graph")[i])
facet.axis("off")
try: # For issues with downloading/parsing in CI
add_basemap(facet)
except:
pass
nx.draw(
G_primal, {n: [n[0], n[1]] for n in list(G_primal.nodes)}, ax=ax[1], node_size=50
)

构建对偶图。momepy 将行属性存储为节点属性,并自动测量线之间的角度。
G_dual = momepy.gdf_to_nx(streets, approach="dual")
# Plot
f, ax = plt.subplots(1, 2, figsize=(12, 6), sharex=True, sharey=True)
streets.plot(color="k", ax=ax[0])
for i, facet in enumerate(ax):
facet.set_title(("Streets", "Graph")[i])
facet.axis("off")
try: # For issues with downloading/parsing in CI
add_basemap(facet)
except:
pass
nx.draw(G_dual, {n: [n[0], n[1]] for n in list(G_dual.nodes)}, ax=ax[1], node_size=50)
plt.show()
# Convert dual graph back to GeoDataFrame. Returns only original line geometry.
lines = momepy.nx_to_gdf(G_dual)

我们也可以使用 PySAL 构建对偶图。注意,它只编码几何对象之间的关系,不存储任何属性。然而,它比 momepy.gdf_to_nx() 快得多。创建 PySAL 权重(图)。
W = weights.Queen.from_dataframe(streets)
# Convert the graph to networkx
G_dual = W.to_networkx()
脚本总运行时间: (0 分钟 17.245 秒)