我的数据框如下:
d = {
'id': [1, 2, 3, 4, 5],
'is_overdue': [True, False, True, True, False],
'org': ['A81001', 'A81002', 'A81001', 'A81002', 'A81003']
}
df = pd.DataFrame(data=d)
现在我想为每个组织解决,过期的行数百分比,以及没有的百分比。
我知道如何按组织分组和逾期状态:
df.groupby(['org', 'is_overdue']).agg('count')
但我如何按组织获得比例?我想最终得到这样的东西:
org is_overdue not_overdue proportion_overdue
A81001 2 0 100
A81002 1 1 50
A81003 0 1 0
答案 0 :(得分:5)
您可以使用DataFrame.apply
。
组织的第一组,并计算逾期/未逾期的数量。然后计算百分比。
df_overdue = df.groupby(['org']).apply(lambda dft: pd.Series({'is_overdue': dft.is_overdue.sum(), 'not_overdue': (~dft.is_overdue).sum()}))
df_overdue['proportion_overdue'] = df_overdue['is_overdue'] / (df_overdue['not_overdue'] + df_overdue['is_overdue'])
print(df_overdue)
输出
is_overdue not_overdue proportion_overdue
org
A81001 2 0 1.0
A81002 1 1 0.5
A81003 0 1 0.0
答案 1 :(得分:4)
您可以使用pd.crosstab
创建频率表 - 即计算每个is_overdue
的{{1}}个数。
org
产量
import pandas as pd
d = {
'id': [1, 2, 3, 4, 5],
'is_overdue': [True, False, True, True, False],
'org': ['A81001', 'A81002', 'A81001', 'A81002', 'A81003']
}
df = pd.DataFrame(data=d)
result = pd.crosstab(index=df['org'], columns=df['is_overdue'], margins=True)
result = result.rename(columns={True:'is_overdue', False:'not overdue'})
result['proportion'] = result['is_overdue']/result['All']*100
print(result)
答案 2 :(得分:2)
有更有效的方法可以做到这一点,但由于您最初尝试使用聚合函数,这是使用聚合函数解决问题的方法:
df.is_overdue = df.is_overdue.map({True: 1, False: 0})
df.groupby(['org'])['is_overdue'].agg({'total_count':'count', 'is_overdue': 'sum'}).reset_index()
现在你可以很容易地计算not_overdue和proportion_overdue。