Pandas一个衬里通过nunique过滤行在特定列上计数

时间:2017-11-21 14:07:52

标签: python pandas

在pandas中,我经常使用以下内容按发生次数过滤数据框

df = df.groupby('A').filter(lambda x: len(x) >= THRESHOLD)

假设df有另一列'B',我想通过该列上唯一值的计数来过滤数据帧,我希望像

df = df.groupby('A').filter(lambda x: len(np.unique(x['B'])) >= THRESHOLD2)

但这似乎不起作用,什么是正确的方法?

1 个答案:

答案 0 :(得分:10)

它应该与nunique

一起使用
df = pd.DataFrame({'B':list('abccee'),
                   'E':[5,3,6,9,2,4],
                   'A':list('aabbcc')})

print (df)
   A  B  E
0  a  a  5
1  a  b  3
2  b  c  6
3  b  c  9
4  c  e  2
5  c  e  4

THRESHOLD2 = 2
df1 = df.groupby('A').filter(lambda x: x['B'].nunique() >= THRESHOLD2)
print (df1)
   A  B  E
0  a  a  5
1  a  b  3

但如果需要更快的解决方案,请使用transform并按boolean indexing过滤:

df2 = df[df.groupby('A')['B'].transform('nunique') >= THRESHOLD2]
print (df2)
   A  B  E
0  a  a  5
1  a  b  3

<强>计时

np.random.seed(123)
N = 1000000
L = list('abcde') 
df = pd.DataFrame({'B': np.random.choice(L, N, p=(0.75,0.0001,0.0005,0.0005,0.2489)),
                   'A':np.random.randint(10000,size=N)})
df = df.sort_values(['A','B']).reset_index(drop=True)
print (df)

THRESHOLD2 = 3

In [403]: %timeit df.groupby('A').filter(lambda x: x['B'].nunique() >= THRESHOLD2)
1 loop, best of 3: 3.05 s per loop

In [404]: %timeit df[df.groupby('A')['B'].transform('nunique')>= THRESHOLD2]
1 loop, best of 3: 558 ms per loop

警告

考虑到组的数量,结果不能解决性能问题,这会对某些解决方案的时间产生很大的影响。