如何使用 GeoDataFrame 执行更复杂的空间连接?

发布于 2025-01-16 23:03:39 字数 1591 浏览 4 评论 0原文

给定两个 GeoDataFrameg1g2,我想从 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 GeoDataFrames, 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 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。
列表为空,暂无数据
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文