Groupby套用无Lambda的筛选器

时间:2018-06-26 14:29:03

标签: pandas pandas-groupby

假设我有此数据:

data = {
    'batch_no': [42, 42, 52, 52, 52, 73],     
    'quality': ['OK', 'NOT OK', 'OK', 'NOT OK', 'NOT OK', 'OK'], 
     }
df = pd.DataFrame(data, columns = ['batch_no', 'quality'])

这为我提供了以下数据框

batch_no    quality
42          OK
42          NOT OK
52          OK
52          NOT OK
52          NOT OK
73          OK

现在我需要为每个NOT OK找到batch_no的计数。

我可以使用groupbyapply通过lamda函数来实现此目的,如下所示:

df.groupby('batch_no')['quality'].apply(lambda x: x[x.eq('NOT OK')].count())

这给了我以下期望的输出

batch_no
42              1
52              2
73              0

但是,即使在我大约300万行的中等大小的数据上,这也非常慢,并且不能满足我的需求。

是否有一种快速的替代方法?

4 个答案:

答案 0 :(得分:3)

您可以比较列quality,然后按batch_no比较groupby并汇总sumTrue的过程类似于1,因此算在内值:

df = df['quality'].eq('NOT OK')
                  .groupby(df['batch_no']).sum()
                  .astype(int)
                  .reset_index(name='count')
print (df)
   batch_no  count
0        42      1
1        52      2
2        73      0

详细信息:

print (df['quality'].eq('NOT OK'))
0    False
1     True
2    False
3     True
4     True
5    False
Name: quality, dtype: bool

答案 1 :(得分:3)

您可以使用

In [77]: df.quality.eq('NOT OK').groupby(df.batch_no).sum()
Out[77]:
batch_no
42    1.0
52    2.0
73    0.0
Name: quality, dtype: float64

答案 2 :(得分:3)

这将提供所有值计数

df.groupby('batch_no').quality.value_counts().unstack(fill_value=0)
Out[231]: 
quality   NOT OK  OK
batch_no            
42             1   1
52             2   1
73             0   1

使用crosstab

pd.crosstab(df.batch_no,df.quality)
Out[242]: 
quality   NOT OK  OK
batch_no            
42             1   1
52             2   1
73             0   1

答案 3 :(得分:3)

使用pd.factorizenp.bincount

f, u = pd.factorize(df.batch_no)
pd.Series(np.bincount(f, df.quality.eq('NOT OK')).astype(int), u)

42    1
52    2
73    0
dtype: int64

合并'OK'(受Wen启发)

i, r = pd.factorize(df.batch_no)
j = df.quality.eq('NOT OK')

pd.DataFrame(
    np.bincount(i * 2 + j, minlength=len(r) * 2).reshape(len(r), -1),
    r, ['OK', 'NOT OK']
)

    OK  NOT OK
42   1       1
52   1       2
73   1       0