注意

This page was generated from gallery/spatial_joins.ipynb.
Interactive online version: Binder badge

空间连接#

一个 空间连接 使用 二元谓词 ,例如 intersectscrosses ,根据它们几何形状之间的空间关系来组合两个 GeoDataFrames

一个常见的用例可能是点层与多边形层之间的空间连接,在这种情况下,您希望保留点几何形状并获取相交多边形的属性。

illustration

空间连接的类型#

我们目前支持以下空间连接方法。我们指的是left_dfright_df,它们对应于作为参数传入的两个数据框。

左外连接#

在左外连接 (how='left') 中,我们保留 所有 来自左侧的行,并在必要时复制它们以表示两个数据框之间的多个匹配。如果右侧的属性相交,我们会保留这些属性,而丢失没有相交的右侧行。左外连接意味着我们对保留左侧的几何体感兴趣。

这相当于PostGIS查询:

SELECT pts.geom, pts.id as ptid, polys.id as polyid
FROM pts
LEFT OUTER JOIN polys
ON ST_Intersects(pts.geom, polys.geom);

                    geom                    | ptid | polyid
--------------------------------------------+------+--------
 010100000040A9FBF2D88AD03F349CD47D796CE9BF |    4 |     10
 010100000048EABE3CB622D8BFA8FBF2D88AA0E9BF |    3 |     10
 010100000048EABE3CB622D8BFA8FBF2D88AA0E9BF |    3 |     20
 0101000000F0D88AA0E1A4EEBF7052F7E5B115E9BF |    2 |     20
 0101000000818693BA2F8FF7BF4ADD97C75604E9BF |    1 |
(5 rows)

右外连接#

在 RIGHT OUTER JOIN (how='right') 中,我们保留 所有 右侧的行,并在必要时重复它们以表示两个数据框之间的多个匹配。如果左侧的行相交,我们保留其属性,并丢弃那些没有相交的左侧行。右外连接意味着我们对保留右侧的几何图形感兴趣。

这相当于PostGIS查询:

SELECT polys.geom, pts.id as ptid, polys.id as polyid
FROM pts
RIGHT OUTER JOIN polys
ON ST_Intersects(pts.geom, polys.geom);

  geom    | ptid | polyid
----------+------+--------
 01...9BF |    4 |     10
 01...9BF |    3 |     10
 02...7BF |    3 |     20
 02...7BF |    2 |     20
 00...5BF |      |     30
(5 rows)

内连接#

在内连接 (how='inner') 中,我们仅保留左右两侧其二元谓词为 True 的行。如果有必要,我们会复制它们以表示两个数据框之间的多个匹配。我们仅保留左右两侧的属性,如果它们相交,并失去所有不相交的行。内连接意味着我们有兴趣保留左侧的几何形状。

这相当于 PostGIS 查询:

SELECT pts.geom, pts.id as ptid, polys.id as polyid
FROM pts
INNER JOIN polys
ON ST_Intersects(pts.geom, polys.geom);

                    geom                    | ptid | polyid
--------------------------------------------+------+--------
 010100000040A9FBF2D88AD03F349CD47D796CE9BF |    4 |     10
 010100000048EABE3CB622D8BFA8FBF2D88AA0E9BF |    3 |     10
 010100000048EABE3CB622D8BFA8FBF2D88AA0E9BF |    3 |     20
 0101000000F0D88AA0E1A4EEBF7052F7E5B115E9BF |    2 |     20
(4 rows)

两个GeoDataFrames之间的空间连接#

让我们看看如何使用 GeoPandas 来实现这些。首先,将纽约市测试数据加载到 GeoDataFrames 中:

[1]:
%matplotlib inline
from shapely.geometry import Point
from geopandas import GeoDataFrame, read_file
import geodatasets

# NYC Boros
zippath = geodatasets.get_path("nybb")
polydf = read_file(zippath)

# Generate some points
b = [int(x) for x in polydf.total_bounds]
N = 8
pointdf = GeoDataFrame(
    [
        {"geometry": Point(x, y), "value1": x + y, "value2": x - y}
        for x, y in zip(
            range(b[0], b[2], int((b[2] - b[0]) / N)),
            range(b[1], b[3], int((b[3] - b[1]) / N)),
        )
    ]
)

# Make sure they're using the same projection reference
pointdf.crs = polydf.crs
[2]:
pointdf
[2]:
几何 值1 值2
0 点 (913175 120121) 1033296 793054
1 点 (932450 139211) 1071661 793239
2 点 (951725 158301) 1110026 793424
3 点 (971000 177391) 1148391 793609
4 POINT (990275 196481) 1186756 793794
5 POINT (1009550 215571) 1225121 793979
6 点 (1028825 234661) 1263486 794164
7 点 (1048100 253751) 1301851 794349
8 POINT (1067375 272841) 1340216 794534
[3]:
polydf
[3]:
行政区代码 行政区名称 形状长度 形状面积 几何
0 5 史坦顿岛 330470.010332 1.623820e+09 MULTIPOLYGON (((970217.022 145643.332, 970227....
1 4 皇后区 896344.047763 3.045213e+09 MULTIPOLYGON (((1029606.077 156073.814, 102957...
2 3 布鲁克林 741080.523166 1.937479e+09 MULTIPOLYGON (((1021176.479 151374.797, 102100...
3 1 曼哈顿 359299.096471 6.364715e+08 多边形 (((981219.056 188655.316, 980940....
4 2 布朗克斯 464392.991824 1.186925e+09 MULTIPOLYGON (((1012821.806 229228.265, 101278...
[4]:
pointdf.plot()
[4]:
<Axes: >
../_images/gallery_spatial_joins_6_1.png
[5]:
polydf.plot()
[5]:
<Axes: >
../_images/gallery_spatial_joins_7_1.png

连接#

[6]:
join_left_df = pointdf.sjoin(polydf, how="left")
join_left_df
# Note the NaNs where the point did not intersect a boro
[6]:
几何 值1 值2 右索引 区代码 区名称 形状长度 形状面积
0 点 (913175 120121) 1033296 793054
1 POINT (932450 139211) 1071661 793239 0.0 5.0 斯塔滕岛 330470.010332 1.623820e+09
2 POINT (951725 158301) 1110026 793424 0.0 5.0 斯坦顿岛 330470.010332 1.623820e+09
3 POINT (971000 177391) 1148391 793609 无效值 无效值 无效值 无效值 无效值
4 POINT (990275 196481) 1186756 793794 无效值 无效值 无效值 无效值 无效值
5 POINT (1009550 215571) 1225121 793979 1.0 4.0 皇后区 896344.047763 3.045213e+09
6 POINT (1028825 234661) 1263486 794164 4.0 2.0 布朗克斯 464392.991824 1.186925e+09
7 POINT (1048100 253751) 1301851 794349
8 POINT (1067375 272841) 1340216 794534 缺失值 缺失值 缺失值 缺失值 缺失值
[7]:
join_right_df = pointdf.sjoin(polydf, how="right")
join_right_df
# Note Staten Island is repeated
[7]:
左索引 值1 值2 区代码 区名称 形状长度 形状面积 几何形状
0 1.0 1071661.0 793239.0 5 斯塔滕岛 330470.010332 1.623820e+09 MULTIPOLYGON (((970217.022 145643.332, 970227....
0 2.0 1110026.0 793424.0 5 史泰登岛 330470.010332 1.623820e+09 MULTIPOLYGON (((970217.022 145643.332, 970227....
1 5.0 1225121.0 793979.0 4 皇后区 896344.047763 3.045213e+09 MULTIPOLYGON (((1029606.077 156073.814, 102957...
2 NaN NaN NaN 3 布鲁克林 741080.523166 1.937479e+09 MULTIPOLYGON (((1021176.479 151374.797, 102100...
3 NaN NaN NaN 1 曼哈顿 359299.096471 6.364715e+08 MULTIPOLYGON (((981219.056 188655.316, 980940....
4 6.0 1263486.0 794164.0 2 布朗克斯 464392.991824 1.186925e+09 MULTIPOLYGON (((1012821.806 229228.265, 101278...
[8]:
join_inner_df = pointdf.sjoin(polydf, how="inner")
join_inner_df
# Note the lack of NaNs; dropped anything that didn't intersect
[8]:
几何 值1 值2 右索引 区代码 区名称 形状长度 形状面积
1 POINT (932450 139211) 1071661 793239 0 5 史泰登岛 330470.010332 1.623820e+09
2 POINT (951725 158301) 1110026 793424 0 5 斯塔滕岛 330470.010332 1.623820e+09
5 POINT (1009550 215571) 1225121 793979 1 4 皇后区 896344.047763 3.045213e+09
6 POINT (1028825 234661) 1263486 794164 4 2 布朗克斯 464392.991824 1.186925e+09

我们不仅限于使用 intersection 二元谓词。可以通过指定 predicate 关键字参数使用任何返回布尔值的 Shapely 几何方法。

[9]:
pointdf.sjoin(polydf, how="left", predicate="within")
[9]:
几何 值1 值2 右索引 区代码 区名称 形状长度 形状面积
0 点 (913175 120121) 1033296 793054
1 POINT (932450 139211) 1071661 793239 0.0 5.0 斯塔滕岛 330470.010332 1.623820e+09
2 POINT (951725 158301) 1110026 793424 0.0 5.0 斯坦顿岛 330470.010332 1.623820e+09
3 POINT (971000 177391) 1148391 793609 无效值 无效值 无效值 无效值 无效值
4 POINT (990275 196481) 1186756 793794 无效值 无效值 无效值 无效值 无效值
5 POINT (1009550 215571) 1225121 793979 1.0 4.0 皇后区 896344.047763 3.045213e+09
6 POINT (1028825 234661) 1263486 794164 4.0 2.0 布朗克斯 464392.991824 1.186925e+09
7 POINT (1048100 253751) 1301851 794349
8 POINT (1067375 272841) 1340216 794534 缺失值 缺失值 缺失值 缺失值 缺失值

我们还可以使用 sjoin_nearest 进行最近邻连接。

[10]:
pointdf.sjoin_nearest(polydf, how="left", distance_col="Distances")
# Note the optional Distances column with computed distances between each point
# and the nearest polydf geometry.
[10]:
几何 值1 值2 右索引 区代码 区名称 形状长度 形状面积 距离
0 POINT (913175 120121) 1033296 793054 0 5 斯塔滕岛 330470.010332 1.623820e+09 1479.291092
1 POINT (932450 139211) 1071661 793239 0 5 斯塔滕岛 330470.010332 1.623820e+09 0.000000
2 POINT (951725 158301) 1110026 793424 0 5 斯塔滕岛 330470.010332 1.623820e+09 0.000000
3 POINT (971000 177391) 1148391 793609 2 3 布鲁克林 741080.523166 1.937479e+09 5075.979291
4 POINT (990275 196481) 1186756 793794 2 3 布鲁克林 741080.523166 1.937479e+09 22.361467
5 POINT (1009550 215571) 1225121 793979 1 4 皇后区 896344.047763 3.045213e+09 0.000000
6 POINT (1028825 234661) 1263486 794164 4 2 布朗克斯 464392.991824 1.186925e+09 0.000000
7 POINT (1048100 253751) 1301851 794349 4 2 布朗克斯 464392.991824 1.186925e+09 818.940377
8 POINT (1067375 272841) 1340216 794534 4 2 布朗克斯 464392.991824 1.186925e+09 25368.109000