我有一个看起来像这样的数据框:
id status year
1 yes 2014
3 no 2013
2 yes 2014
4 no 2014
实际数据框非常大,具有多个ID和年份。我正在尝试创建一个新的数据框,其中包含按年份分组的“是”和“否”的百分比。
我当时正在考虑按年份对数据框进行分组,然后将每年的状态放在列表中,然后以这种方式分析是和否的计数,但是我想知道是否还有一种更Python化的方法这个吗?
我希望最终数据帧看起来像这样:
year yes_count no_count ratio_yes_to_toal
2013 0 1 0%
2014 2 1 67%
答案 0 :(得分:2)
我建议按year
和status
分组,计数,旋转并创建比例的其他列:
df2 = df.groupby(['year', 'status']).count().pivot_table(index="year", columns=["status"]).fillna(0)
df2.columns = df2.columns.get_level_values(1)
df2['ratio'] = df2['yes'] / (df2['yes'] + df2['no'])
输出
status no yes ratio
year
2013 1.0 0.0 0.000000
2014 1.0 2.0 0.666667
答案 1 :(得分:2)
您可以使用pivot_table
而不使用groupby以获得更快的解决方案。
v = df.pivot_table(index='year', columns='status', aggfunc='size').fillna(0)
v.join((v['yes'] / v.sum(1)).to_frame('ratio'))
# Or, if you care about micro-optimizing the code,
# v['ratio'] = v['yes'] / v.sum(1)
no yes ratio
year
2013 1.0 0.0 0.000000
2014 1.0 2.0 0.666667
答案 2 :(得分:1)
要获取计数和百分比,可能最简单的方法是分两步进行操作:groupby
+ value_counts
+ unstack
,然后进行除法。
df1 = df.groupby('year').status.value_counts().unstack(1).fillna(0)
df1['ratio_yes'] = df1['yes'].div(df1.sum(1), axis=0)*100
#status no yes ratio_yes
#year
#2013 1.0 0.0 0.000000
#2014 1.0 2.0 66.666667
如果只需要百分比,则可以添加normalize=True
参数,并一步一步完成:
df1 = df.groupby('year').status.value_counts(normalize=True).unstack(1).fillna(0)*100
#status no yes
#year
#2013 100.000000 0.000000
#2014 33.333333 66.666667
答案 3 :(得分:0)
pd.crosstab
您可以交叉列表化数据框,然后计算比率:
res = pd.crosstab(df['year'], df['status'])
res['yes_pct'] = res['yes'].div(res.sum(1))
print(res)
status no yes yes_pct
year
2013 1 0 0.000000
2014 1 2 0.666667