【问题标题】:Efficient way to find which row a pair of GPS coordinates belong to查找一对GPS坐标属于哪一行的有效方法
【发布时间】:2019-11-18 06:29:11
【问题描述】:

我有一个带有一组 GPS 纬度/经度坐标的数据框(称为 A)

Lat | Long
28.6752213, 77.09311140000001

我有另一个 CSV(有很多行,超过一百万 - 称之为 B)的形式

这基本上是一个网格,具有 4 个角的纬度/经度坐标。

问题

我需要找到 A 中的每一行,它在 B 中由哪个(非唯一)行界定。如中所示,gps 坐标位于框内,如 B 中的行所述。我有一个函数当给定来自 A 的坐标和 B 中的行时,返回 True/False

现在我正在使用蛮力方法,遍历整个 B 数据框并检查每一行是否属于该框。但是,这非常低效且非常缓慢。

我确信必须有更好的方法来解决这个问题,因为这是一个常见问题。谁能指点我?

谢谢! :)

编辑:

用于查找特定 gps_coord 是否属于由行定义的框的函数的代码

import matplotlib.path as path
def find_if_point_in_bounding_box(row,gps_coords):
    top_left_lat = row['top_left_lat']
    top_left_long = row['top_left_long']
    top_right_lat = row['top_right_lat']
    top_right_long = row['top_right_long']
    bottom_left_lat = row['bottom_left_lat']
    bottom_left_long = row['bottom_left_long']
    bottom_right_lat = row['bottom_right_lat']
    bottom_right_long = row['bottom_right_long']

    lat,long = gps_coords
     # create box
    p = path.Path([(top_left_lat, top_left_long),(top_right_lat,top_right_long),(bottom_left_lat,bottom_left_long),(bottom_right_lat,bottom_right_long)])
    res = p.contains_points([(lat,long)])[0]
    return res

【问题讨论】:

  • 为什么会有冗余?框可以由左上角和右下角坐标定义。 top_right_latbottorm_right_lat 总是相同的值,等等。
  • @VictorRuiz:这不是很有帮助。 GeoPandas 可以很好地处理这些问题。
  • 您目前是如何处理逆经的?换句话说,您是否有任何跨越国际日期变更线的边界框(*_left_lon > 0*_right_lon < 0)?
  • 不知道 GeoPandas。但我确信使用数据库和查询比迭代每一行数据以搜索满足某些条件的数据(如果这种条件可以表示为查询)更好。但是您可以使用 GeoPandas 分享如何做到这一点
  • @VictorRuiz:请注意,Pandas 提供的索引就像数据库一样。这些不是要按顺序扫描的简单列表。

标签: python pandas geo


【解决方案1】:

您的 8 个坐标中的每一个仅包含 4 个唯一值:2 个纬度(形成每个框的顶部和底部边界,或南北边界)和两个经度(左右边界,西风和东风)。在 4 个角的 4 个(纬度,经度)组合之间,您会看到有重复的值。您只需将您的位置与 4 个边界进行比较,纬度应位于(或位于)两个纬度边界之间,经度应位于两个经度边界之间。

因此,您可以简单地根据top_*_latbottom_*_lat 中的一个为纬度,以及*_left_long*_right_long 中的每个为经度,请求具有匹配边界框的行:

lat, long = <latitude>, <longitude>
matching_rows = df.query(
    # top and bottom latitudes, top lat > bottom lat, north to south
    "top_left_lat >= @lat >= bottom_right_lat and "
    # left and right longitudes, left long < right long, west to east
    "top_left_long <= @long <= bottom_right_long"
)

上面的pandas.DataFrame.query() expression 只是做了一个简单的几何点包含测试,并假设您的边界框不越过反子午线(国际日期变更线)也不与任何一个极点重叠。

您必须为输入数据框中的每个位置执行此操作; Pandas 还不能基于任意表达式合并数据帧。您可以按两个坐标之一对输入进行分组,以生成与该坐标匹配的行子集,然后在每个组的第二个坐标上进一步过滤它们。

如果您的输入数据框也非常大,那么使用数据库进行此类连接可能会更好。

【讨论】:

  • 嗨Martijin,感谢您的回复!像这样查询坐标真是太天才了。我测试了查询,但结果似乎与框功能不一致。 [find_if_point_in_bounding_box(matching_rows.loc[i],(lat,lon)) for i in matching_rows.index] 的每个结果都返回 False。如果需要,我在问题中添加了 find_if_ 等代码
  • @Wboy:恐怕你的函数错了。您定义了 Z 路径。
  • @Wboy:对不起,我认为这是一个不同的 Path 对象。您似乎正在使用 matplotlib 的路径?然后你正在测试沙漏形状的遏制。您混淆了底部坐标。
  • 等等..什么。真的吗?所以它的p = path.Path([(top_left_lat, top_left_long),(top_right_lat,top_right_long),(bottom_right_lat,bottom_right_long),bottom_left_lat,bottom_left_long)])?
  • 我尝试了上述方法并重新运行了一个测试用例,但它再次显示所有 False。我使用mapcustomizer.com/# 手动检查并使用 28.617771 77.2225269 作为输入测试用例。 matching_rows 的第一行给出了框的以下坐标:28.619513,77.224254 28.619513,77.226280 28.617732,77.226280 28.617732,77.224254 但如果你绘制它,你会发现它不在框内
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2020-08-06
  • 1970-01-01
  • 2017-12-18
  • 2013-03-26
  • 2015-12-02
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多