如何使用 GeoDataFrame 执行更复杂的空间连接?
给定两个 GeoDataFrame
,g1
、g2
,我想从 g1
获取不 g1
的所有行em>与g2
中的任何行相交,或者仅接触它们。
为此,我在界面中缺少一些操作:(
- 左)半连接(在通过右侧的二进制谓词过滤后仅保留左侧的数据)
- (左)反连接(仅保留不存在的行)用右侧的任何行满足二元谓词)
- 二元谓词的逻辑运算符(OR、NOT、AND 等)。
- 唯一(不要在多次命中时重复左侧行)
我希望能够编写这样的查询:
result = g1.sjoin(g2, how="left-anti-semi", predicate="intersects & ~touches")
或者至少:
intersect_but_not_touch = lambda left_shape, right_shape: left_shape.intersects(right_shape) and not left_shape.touches(right_shape)
joined = g1.sjoin(g2, how="left", predicate=intersect_but_not_touch)
result = joined.query('right_index != right_index') # anti-join.
但我没有看到任何组合谓词或将函数作为谓词传递的方法。有没有办法通过 sjoin 来做到这一点,还是我们必须“手动”做到这一点?
这是我到目前为止得到的解决方案,但这太复杂了:
# Duplicate geometry column so it remains after sjoin.
g2["right_geometry"] = g2["geometry"]
intersect = g1.sjoin(g2, how="left")
# right index is Nan, no intersection found.
dont_intersect = intersect.query("right_index != right_index") # anti-join
intersect = intersect.query("right_index == right_index")
# row-wise "touches" predicate.
intersect["just_touch"] = intersect.touches(intersect["right_geometry"])
intersect_but_just_touch = intersect.groupby(intersect.index).filter(
lambda x: x.just_touch.all()
)
result = pd.concat([dont_intersect, intersect_but_just_touch])
Given two GeoDataFrame
s, g1
, g2
, I want to get all the rows from g1
which do not intersect any rows from g2
, or only touch them.
For this there are some operations which I am missing in the interface:
- (Left) Semi-Join (only keep data from left side after filtering it by binary predicate with right side)
- (Left) Anti-Join (only keep rows that do not fulfill the binary predicate with any of the rows of the right side)
- Logical operators (OR, NOT, AND, etc.) for the binary predicate.
- Unique (do not duplicate left rows on multiple hits)
I would like to be able to write a query like this:
result = g1.sjoin(g2, how="left-anti-semi", predicate="intersects & ~touches")
Or at least:
intersect_but_not_touch = lambda left_shape, right_shape: left_shape.intersects(right_shape) and not left_shape.touches(right_shape)
joined = g1.sjoin(g2, how="left", predicate=intersect_but_not_touch)
result = joined.query('right_index != right_index') # anti-join.
But I did not see any way to combine predicates, or to pass a function as a predicate. Is there any way to do any of that with sjoin
or do we have to do that "manually"?
This is the solution I have got so far, but this is far too complicated:
# Duplicate geometry column so it remains after sjoin.
g2["right_geometry"] = g2["geometry"]
intersect = g1.sjoin(g2, how="left")
# right index is Nan, no intersection found.
dont_intersect = intersect.query("right_index != right_index") # anti-join
intersect = intersect.query("right_index == right_index")
# row-wise "touches" predicate.
intersect["just_touch"] = intersect.touches(intersect["right_geometry"])
intersect_but_just_touch = intersect.groupby(intersect.index).filter(
lambda x: x.just_touch.all()
)
result = pd.concat([dont_intersect, intersect_but_just_touch])
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论