我想在pandas中进行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'))
在 pandas 中我只能得到 total
和 numOfSuccess
为:
df_new = df.groupby(['type'], as_index=False)['success'].agg({'total':'count', 'numOfSuccess':'sum'})
或仅总计:
df = df.groupby(['type']).size().reset_index(name='NumOfReqs')
但我无法获得第三列numOfFailures
,而且如果有替代方案而不是对 bool 值求和,那就更好了,因为在我看来,in可以扩展到其他情况也更容易.
我怎样才能做到这一点?
最佳答案
使用groupby
与 GroupBy.size
为了计算所有数据,然后对于每个类别的计数需要旋转 - 使用 GroupBy.size
和 unstack
, crosstab
或pivot_table
:
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
另一个解决方案是在 crosstab
中使用参数 margins
并通过使用 iloc
进行索引来删除最后一行:
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
编辑:如果可能 True
或 False
不存在,请添加 reindex
添加缺失的列:
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
关于python - Pandas 群by : counting rows satisfying condition on other columns?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54307039/