在 Panda DataFrame 中过滤 groupby 数据的有效方法

Posted

技术标签:

【中文标题】在 Panda DataFrame 中过滤 groupby 数据的有效方法【英文标题】:Efficient way of filtering groupby data in a Panda DataFrame 【发布时间】:2019-09-12 00:14:50 【问题描述】:

问题

我有两个数据框Frame A(保存一些原始数据)和Frame B(保存阈值数据)。

我的目标是针对Frame B 中的每个ID 我想返回Frame A 中对应ID 的行<= b['A']

我写的代码运行良好,我的问题是效率。框架 B 有大约 100K 行,而框架 A 有大约 1M 行。根据快速计算,我需要大约 6 个小时来过滤我的数据。虽然 6 小时可能是可行的(我可以让它在一夜之间运行),但这个数据集代表了我数据的一小部分样本,约占我总数据集的 5%。

我的尝试

import pandas as pd
from io import StringIO

data1 = """
id,A,B,C,D
123,2019-09-10 00:00:00,1,True,False
123,2019-09-10 00:10:00,1,True,False
123,2019-09-11 00:07:00,1,True,False
456,2019-09-05 01:00:00,1,True,False
456,2019-09-08 10:00:00,1,True,False
789,2019-09-10 10:00:00,1,True,False
789,2019-09-11 00:50:00,1,True,False
789,2019-09-12 12:00:00,1,True,False
"""

data2 = """
id,A,B
123,2019-09-10 00:10:00,1
456,2019-09-05 01:00:00,1
789,2019-09-12 12:00:00,1
"""

df_a = pd.read_csv(StringIO(data1))
df_b = pd.read_csv(StringIO(data2))

dfs = []
for Id in df_b.id.unique():
    df = df_a[df_a.id == Id]
    df = df[df['A'] <= df_b[df_b.id == Id]['A'].values[0]]
    dfs.append(df)

print(pd.concat(dfs))

数据

期望的输出

    id                    A  B     C      D
0  123  2019-09-10 00:00:00  1  True  False
1  123  2019-09-10 00:10:00  1  True  False
3  456  2019-09-05 01:00:00  1  True  False
5  789  2019-09-10 10:00:00  1  True  False
6  789  2019-09-11 00:50:00  1  True  False
7  789  2019-09-12 12:00:00  1  True  False

A 帧

   id                    A  B     C      D
0  123  2019-09-10 00:00:00  1  True  False
1  123  2019-09-10 00:10:00  1  True  False
2  123  2019-09-11 00:07:00  1  True  False
3  456  2019-09-05 01:00:00  1  True  False
4  456  2019-09-08 10:00:00  1  True  False
5  789  2019-09-10 10:00:00  1  True  False
6  789  2019-09-11 00:50:00  1  True  False
7  789  2019-09-12 12:00:00  1  True  False

帧 B

    id                    A  B
0  123  2019-09-10 00:10:00  1
1  456  2019-09-05 01:00:00  1
2  789  2019-09-12 12:00:00  1

【问题讨论】:

将您的数据放入任何 SQL 数据库并在那里执行。 @AidanGawronski,必须解决基础架构限制和跨团队/环境的复制问题 :) 【参考方案1】:

使用map

s = df_a.id.map(dict(df_b[['id', 'A']].values))
df_a[df_a.A <= s]

Out[35]:
    id                   A  B     C      D
0  123 2019-09-10 00:00:00  1  True  False
1  123 2019-09-10 00:10:00  1  True  False
3  456 2019-09-05 01:00:00  1  True  False
5  789 2019-09-10 10:00:00  1  True  False
6  789 2019-09-11 00:50:00  1  True  False
7  789 2019-09-12 12:00:00  1  True  False

使用左边的mergequery

(df_a.merge(df_b[['id', 'A']], on='id', how='left', suffixes=('','_y'))
     .query('A <= A_y').drop('A_y', 1))

Out[43]:
    id                   A  B     C      D
0  123 2019-09-10 00:00:00  1  True  False
1  123 2019-09-10 00:10:00  1  True  False
3  456 2019-09-05 01:00:00  1  True  False
5  789 2019-09-10 10:00:00  1  True  False
6  789 2019-09-11 00:50:00  1  True  False
7  789 2019-09-12 12:00:00  1  True  False

【讨论】:

太棒了,很棒的解决方案,超级快! @Teddy:很高兴我能帮上忙 :)。我还赞成你关于清晰、详细的信息和样本的问题。你显然是在准备问题上付出了努力。 +1

以上是关于在 Panda DataFrame 中过滤 groupby 数据的有效方法的主要内容,如果未能解决你的问题,请参考以下文章

在 Panda Dataframe 中附加布尔列

Pandas 使用 DataFrame.query 根据字符串长度过滤字符串数据

如何在 Panda MultiIndex Dataframe 中绘制 ylabel

关于panda中dataframe的与&运算*(stackoverflow高票答案)

3-Panda之Series和DataFrame区别

利用python数据分析panda学习笔记之DataFrame