【问题标题】:Pandas: filter large (50M rows) dataframe if row lat/lng falls inside a bounding box?Pandas:如果行 lat/lng 落在边界框内,过滤大(50M 行)数据框?
【发布时间】:2018-01-15 02:42:51
【问题描述】:

我有一个大型数据集,我正在评估各种解析方法。这是一组 csv,每个文件有大约 4000 万行。读入熊猫数据框我有以下示例数据。 (后面的数据是随机生成的)账户标识符会不时重复,有些在盒子里,有些在外面。我使用 csv 阅读器以“蛮力”方式进行这项工作,并且随机生成的 1000 万行样本的处理时间缩短到 60 秒左右。我希望我能用 pandas 更高效,因为真实的数据集要大得多,将来我们可能需要反复进行这种解析。

                            account        lat         lng  
0  f413e6cd-bbfe-463b-bf58-cba1a74a4aff    50.847615     70.826473  
1  8b2ceb89-7ce0-4e14-a5f0-28acb7b05d8b    18.545991     115.078981    
2  a51ab728-14b5-473c-bed1-91953da8ba22    30.699439     9.660661  
3  83e3964f-130f-49bc-9c4b-d46d4b48c2cb    7.906903      70.507260
4  84c75e57-5a5f-4314-80be-d1271ecd76ef    -20.325371    48.310855 

这个块描述了我想要匹配数据帧行的函数。我有多个边界框需要检查成员资格。

top = 49.3457868  # north lat
left = -124.7844079  # west long
right = -66.9513812  # east long
bottom = 24.7433195  # south lat

def in_bounds(lat, lng):
    if bottom <= lat <= top and left <= lng <= right:
        return True
    elif bottom2 <= lat <= top2 and left2 <= lng <= right2:
        return True
    else return False

我真的不明白如何将 lambda 函数应用于所有行,同时使用数据框多列的条件收集新数据框中匹配的行。我在网上找不到任何与此相近的示例。

到目前为止,我的工作如下所示:

df = pd.read_csv('DATA.csv')
df.columns = ['account', 'lat', 'lng']
accounts= df[(bottom <= df.lat) & (df.lat <= top) & (left <= df.lng) & (df.lng <= right)]

results = df[df.account.isin(accounts)]
results.to_csv('pd_out.csv', header=False, )

但这仅适用于单个边界框。我不知道如何进行与上述类似的过滤,但使用我的 in_bounds 函数。那么我怎样才能最好地做到这一点呢?

【问题讨论】:

  • 欢迎来到 Stack Overflow!您可以先take the tour 学习How to Ask a good question 并创建Minimal, Complete, and Verifiable 示例。这让我们更容易为您提供帮助。
  • 这里有很多东西,各种纬度和经度以及一些全局变量,而且......很难全部遵循。
  • @StephenRauch 是的,抱歉,它在我的实际工作中安排得更优雅,但试图将其归结为我无法解决的 Pandas 问题。我确信这只是熊猫的一些技巧,没有很好的记录。我在这里使用的东西只是一个用于处理模拟数据的“玩具脚本”。
  • 如果@tai 没有解决你的问题,那么建议你研究一下 MCVE 链接并构建相同的。

标签: python pandas


【解决方案1】:

不是太漂亮,但是要结合这两个条件,可以使用| 运算符。请注意两个框条件周围的括号。

box1_cond = (bottom <= df.lat) & (df.lat <= top) & (left <= df.lng) & (df.lng <= right)
box2_cond = (bottom2 <= df.lat) & (df.lat <= top2) & (left2 <= df.lng) & (df.lng <= right2)
accounts = df[box1_cond | box2_cond]

【讨论】:

  • 啊哈。这至少有帮助。我没有在文档中找到那种语法示例。如果条件是动态的呢?即,从文件中读取?
  • @ZachSwanson 我不知道。我想你应该看看read_csv函数
  • @ZachSwanson 我能想到的一件事是read_sql 这个函数。如果您将数据存储在 SQL 数据库中,则可以在读取时过滤掉数据。
  • 对不起,我问的另一个问题,我不清楚。我擅长从文件中读取数据。我想知道的是,如果条件列表的大小未知(即边界框可能在文件中定义),我将如何构建与您的答案类似的查询。我想我知道如何通过在数据帧上构建 .query() 并迭代地构建查询来做到这一点,只是不确定这是最佳的。无论如何,感谢答案,这让我的球动起来了!
  • @ZachSwanson 如果你愿意,你可以把它放在一起。还是一步一步做?首先构建初始 df 并对过滤后的 df 进行查询。
猜你喜欢
  • 2011-07-23
  • 1970-01-01
  • 2011-11-19
  • 2021-12-26
  • 2011-02-07
  • 2021-10-24
  • 1970-01-01
  • 1970-01-01
  • 2019-03-29
相关资源
最近更新 更多