在Panda DataFrame中过滤分组依据数据的有效方法

时间:2019-09-12 00:14:50

标签: python pandas bigdata

问题

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

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

我写的代码很好用,我的问题是效率。帧B大约有10万行,而帧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

1 个答案:

答案 0 :(得分:2)

使用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