【问题标题】:Fast check if polygon contains point between dataframes快速检查多边形是否包含数据框之间的点
【发布时间】:2019-12-26 15:22:40
【问题描述】:

我有两个数据框。一个包含一列多边形,取自多边形形状的图像。每个多边形都有一组坐标。这个数据框还有一个“segment-id”列。我有另一个数据框,其中包含一列点,也带有坐标。这些点表示来自同一多边形形状图像的像素,因此具有相同的坐标系。我想给每个点包含它的多边形的“segment-id”。每个多边形至少包含一个点。

目前,我通过使用嵌套的 for 循环来实现这一点:

    for i, row in enumerate(point_df.itertuples(), 0):
        point = pixel_df.at[i, 'geometry']

        for j in range(len(polygon_df)):
              polygon = polygon_df.iat[j, 0]

              if polygon.contains(point):
                  pixel_df.at[i, 'segment_id'] = polygon_df.at[j, 'segment_id']
              else:
                  pass

这非常慢。对于 100 点,大约需要 10 秒。我需要一种更快的方法来做到这一点。我尝试过使用 apply 但它仍然非常慢。

希望有人能帮帮我,非常感谢。

【问题讨论】:

  • 能否贴出慢速部分的反汇编或指令跟踪(poly.contains(point))?
  • 我认为 for 循环是缓慢的部分。但是我现在就试试这个,我没有太多使用调试工具的经验

标签: pandas performance dataframe polygon contains


【解决方案1】:

对于快速“在多边形内的点”:

准备:在获取描述多边形的数据的代码中;使用所有顶点,找到最小和最大 y 坐标,以及最小和最大 x 坐标;并将其与多边形的数据一起存储。

1) 使用点的坐标和多边形的“最小和最大 x 和 y”(在准备过程中预先确定);做一个“边界框”测试。这只是确定该点是否绝对不在多边形内的一种快速方法(因此您可以在大多数情况下跳过更昂贵的步骤)。

2) 将“是/否”标志设置为“否”

3) 对于多边形中的每条边;确定通过该点的水平线是否与边缘相交,以及是否确定相交的 x 坐标。如果交叉点的 x 坐标小于点的 x 坐标,则切换(使用 NOT)“是/否”标志。在此步骤中忽略“水平线穿过顶点”。

4) 对于每个顶点,将其 y 坐标与该点的 y 坐标进行比较。如果它们相同,则需要查看来自该顶点的两条边以确定边的顶点是否在相同的 y 方向上。如果边的顶点在相同的 y 方向(如果边形成“V”形或倒置的“V”形)忽略顶点。否则(如果边形成 '' 形状),如果顶点的 x 坐标小于点的 x 坐标,则切换“是/否”标志。

这一切都完成了; “是/否”标志会告诉您该点是否在多边形中。

【讨论】:

  • 感谢您的回答,但我认为 poly.contains(points) 已经完成了大部分工作。这是一种更快速地遍历两个数据帧的方法。我不认为 if 语句会减慢它的速度。不过非常感谢您的回答!
  • @D.Smith:我(几乎)可以保证poly.contains(point) 是一团糟,会导致 CPU 执行数百万条指令。这就是为什么我之前建议发布反汇编或指令跟踪的原因 - 不是因为我想看到它,而是因为我想让你看到“为方便而设计”的语言对于性能来说是多么可怕。 ;-)
  • @D.Smith:粗略估计;对于大多数语言(汇编、C、C++、C#、Java 等),如果我未能每秒执行数百万次上述算法(仅在一个 CPU 上),我会非常失望。即使对于 python,我仍然希望“每秒近 100 万”的代码好;并且循环开销可能什么都没有(外循环只发生 100 次,而内循环中唯一看起来可能很昂贵的是poly.contains(point))。
猜你喜欢
  • 2015-03-07
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-12-06
  • 2023-03-08
  • 1970-01-01
  • 2014-04-26
相关资源
最近更新 更多