Pandas Groupby--基于多个条件高效选择/过滤组?
我正在努力 根据多个任意条件筛选熊猫中的数据帧组。 但我似乎无法快速到达熊猫“本土”一轮 在这里,我生成了一个包含2*n*n行和4列的示例数据帧:Pandas Groupby--基于多个条件高效选择/过滤组?,pandas,group-by,data-science,Pandas,Group By,Data Science,我正在努力 根据多个任意条件筛选熊猫中的数据帧组。 但我似乎无法快速到达熊猫“本土”一轮 在这里,我生成了一个包含2*n*n行和4列的示例数据帧: import itertools import random n = 100 lst = range(0, n) df = pd.DataFrame( {'A': list(itertools.chain.from_iterable(itertools.repeat(x, n*2) for x in lst)), 'B': li
import itertools
import random
n = 100
lst = range(0, n)
df = pd.DataFrame(
{'A': list(itertools.chain.from_iterable(itertools.repeat(x, n*2) for x in lst)),
'B': list(itertools.chain.from_iterable(itertools.repeat(x, 1*2) for x in lst)) * n,
'C': random.choices(list(range(100)), k=2*n*n),
'D': random.choices(list(range(100)), k=2*n*n)
})
产生数据帧,例如:
A B C D
0 0 0 26 49
1 0 0 29 80
2 0 1 70 92
3 0 1 7 2
4 1 0 90 11
5 1 0 19 4
6 1 1 29 4
7 1 1 31 95
我想
选择按A和B分组的组,
过滤组,直到组中的任何值在C列和D列中都大于50,
一艘班轮应为以下类型:
test.groupby([test.A, test.B]).filter(lambda x: ((x.C>50).any() & (x.D>50).any()) )
产生
A B C D
2 0 1 70 92
3 0 1 7 2
对于较小的数据帧,例如n<20,这一切都是好的。
但是这个解决方案需要相当长的时间,例如,对于大数据帧,当n=100时需要4.58秒
我有一个可供选择的分步解决方案,该解决方案可实现相同的结果,但在n=100时运行速度要快得多,为28.1毫秒:
test_g = test.assign(key_C = test.C>50, key_D = test.D>50).groupby([test.A, test.B])
test_C_bool = test_g.key_C.transform('any')
test_D_bool = test_g.key_D.transform('any')
test[test_C_bool & test_D_bool]
但可以说有点丑陋。我的问题是:
有更好的本地熊猫解决方案吗,和
我的本机解决方案版本的性能次优是否有原因?
奖金问题:
事实上,我只想提取组,而不是与它们的数据一起提取。也就是说,我只需要
A B
0 1
在上面的例子中。有没有一种方法可以在不经过上述中间步骤的情况下对熊猫执行此操作?这与您的第二种方法类似,但被链接在一起:
mask = (df[['C','D']].gt(50) # in the case you have different thresholds for `C`, `D` [50, 60]
.all(axis=1) # check for both True on the rows
.groupby([df['A'],df['B']]) # normal groupby
.transform('max') # 'any' instead of 'max' also works
)
df.loc[mask]
如果不需要数据,可以放弃转换:
这与您的第二种方法类似,但被链接在一起:
mask = (df[['C','D']].gt(50) # in the case you have different thresholds for `C`, `D` [50, 60]
.all(axis=1) # check for both True on the rows
.groupby([df['A'],df['B']]) # normal groupby
.transform('max') # 'any' instead of 'max' also works
)
df.loc[mask]
如果不需要数据,可以放弃转换: