熊猫groupby:计算满足其他列条件的行?

时间:2019-01-22 11:12:51

标签: python pandas group-by pandas-groupby

我想在大熊猫中做一个groupby,以获取一个数据帧,该数据帧具有用于groupby的列,每个组的元素数以及其中的元素数作为列在每个组中,满足/不满足基于另一个列值的条件的元素数。

例如,像这样的输入:

type    success
A       True
B       False
A       False
C       True

我想要类似的东西

type    total    numOfSuccess numOfFailure
A       2        1             1
B       1        0             1
C       1        1             0

在pyspark中,我这样做

import pyspark.sql.functions as F
df = df.groupBy("type").agg(\
    F.count('*').alias('total'), \
    F.sum(F.when(F.col('success')=="true", 1).otherwise(0)).alias('numOfSuccess'),
    F.sum(F.when(F.col('success')!="true", 1).otherwise(0)).alias('numOfFails'))

在大熊猫中,我只能将totalnumOfSuccess设置为:

df_new = df.groupby(['type'], as_index=False)['success'].agg({'total':'count', 'numOfSuccess':'sum'})

或仅将总数设为:

df = df.groupby(['type']).size().reset_index(name='NumOfReqs')

但是我无法获得第三列numOfFailures,而且如果还有替代方法而不是对布尔值求和,那会更好,因为我认为in可以扩展到其他情况,也更容易。

>

我该怎么做?

1 个答案:

答案 0 :(得分:2)

groupbyGroupBy.size一起用于计数所有数据,然后需要对每个类别的计数进行透视-使用GroupBy.sizeunstackcrosstab或{{3 }}:

df1 = df.groupby('type').size().reset_index(name='count')
df2 = (df.groupby(['type', 'success']).size().unstack(fill_value=0)
        .rename(columns={True:'numOfSuccess', False:'numOfFails'}))

df2的替代项:

df2 = pd.crosstab(df['type'], df['success'])
        .rename(columns={True:'numOfSuccess', False:'numOfFails'}))

或者:

df2 = (df.pivot_table(index='type', columns='success', fill_value=0, aggfunc='size')
        .rename(columns={True:'numOfSuccess', False:'numOfFails'}))

df_new = df1.join(df2, on='type')
print (df_new)
  type  count  numOfFails  numOfSuccess
0    A      2           1             1
1    B      1           1             0
2    C      1           0             1

另一种解决方案是在pivot_table中使用参数margins并通过使用crosstab进行索引来删除最后一行:

df = (pd.crosstab(df['type'], df['success'], margins=True)
        .rename(columns={True:'numOfSuccess', False:'numOfFails', 'All':'count'})
        .iloc[:-1]
        .reset_index()
        .rename_axis(None, axis=1))

print (df)
  type  numOfFails  numOfSuccess  count
0    A           1             1      2
1    B           1             0      1
2    C           0             1      1

编辑:如果TrueFalse不存在,请添加iloc来添加缺少的列:

print (df)
  type  success
0    A     True
1    B     True
2    A     True
3    C     True

df1 = df.groupby('type').size().reset_index(name='count')
df2 = (df.groupby(['type', 'success']).size().unstack(fill_value=0)
         .reindex(columns=[True, False], fill_value=0)
         .rename(columns={True:'numOfSuccess', False:'numOfFails'}))


df_new = df1.join(df2, on='type')
print (df_new)
  type  count  numOfSuccess  numOfFails
0    A      2             2           0
1    B      1             1           0
2    C      1             1           0