来自一组线的图形#

这个例子展示了如何使用GeoPandas、Moepy和另一种选择PySAL从一组地理线(有时称为“线串”)构建图形。我们将绘制一些河流和街道,以及它们由线段组成的图表。

从线条几何图形创建图形对象通常有两种方法。让我们用一个街道网络的例子来说明这两个问题:

第一种方法是所谓的原始方法,其中每个交叉点是一个节点,连接两个交叉点的每个线串段都是一条边。

第二种方法是所谓的对偶方法,其中每条线都是一个节点,相交的拓扑结构被转化为边。将其用于街道网络分析的方式之一是角度分析,即通过交叉点上街道段之间的角度对路线进行加权。

我们将使用GeoPandas读取空间数据,并使用omepy生成第一个原始图形,然后生成对偶图形。此外,我们将使用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")

构造原始图。Moepy自动保留GeoDataFrame中的所有属性,然后将其存储为边属性。

G = momepy.gdf_to_nx(rivers, approach="primal")

每个节点都由它的坐标编码,这允许我们在绘图中使用它们。

positions = {n: [n[0], n[1]] for n in list(G.nodes)}

# Plot
f, ax = plt.subplots(1, 2, figsize=(12, 6), sharex=True, sharey=True)
rivers.plot(color="k", ax=ax[0])
for i, facet in enumerate(ax):
    facet.set_title(("Rivers", "Graph")[i])
    facet.axis("off")
nx.draw(G, positions, ax=ax[1], node_size=5)
Rivers, Graph

一旦我们完成了基于图形的分析,我们就可以将图形转换回GeoDataFrames。Moepy可以以点几何形式返回节点,以原始线几何形式返回边和W对象,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")
    add_basemap(facet)
nx.draw(
    G_primal, {n: [n[0], n[1]] for n in list(G_primal.nodes)}, ax=ax[1], node_size=50
)
Streets, Graph

构造对偶图。Omepy会将行属性存储为节点属性,并自动测量行之间的角度。

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")
    add_basemap(facet)
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)
Streets, Graph

我们也可以使用PYSAL来构造对偶图。请注意,它只对几何图形之间的关系进行编码,而不存储任何属性。但是,它比omepy.gdf_to_nx()快得多。创建PYSAL权重(图表)。

W = weights.Queen.from_dataframe(streets)

# Convert the graph to networkx
G_dual = W.to_networkx()

Total running time of the script: ( 0 minutes 12.819 seconds)

Gallery generated by Sphinx-Gallery