pandas:通过两个不同的维度创建数据透视表?

时间:2016-07-25 19:09:01

标签: python pandas

我是一名熊猫新手。我有赞助商和公司的考试数据框:

import pandas pd

df = pd.DataFrame({
  'sponsor': ['A71991', 'A71991', 'A71991', 'A81001', 'A81001'],
  'sponsor_class': ['Industry', 'Industry', 'Industry', 'NIH', 'NIH'],
  'year': [2012, 2013, 2013, 2012, 2013],
  'passed': [True, False, True, True, True],
})

现在我想输出一个CSV文件,每个赞助商及其类别都有一行,以及年份的通行证和总费率列:

sponsor,sponsor_class,2012_total,2012_passed,2013_total,2013_passed
A71991,Industry,1,1,2,1
A81001,NIH,1,1,1,1

如何从df获取此重组数据框?我想我需要按sponsorsponsor_class进行分组,然后按年度计算总计数和passedTrue的计数,然后展平列。 (我知道我以pd.write_csv(mydf)结尾。)

我尝试从这开始:

df_g = df.groupby(['sponsor', 'sponsor_class', 'year', 'passed'])

但这给了我一个空的数据框。

我想我需要一个透视表来移动年份并传递状态......但我不知道从哪里开始。

更新:到达某处:

df_g = df_completed.pivot_table(index=['lead_sponsor', 'lead_sponsor_class'], 
                                columns='year', 
                                aggfunc=len, fill_value=0)
df_g[['passed']]

现在我需要解决(1)如何获取所有行的计数以及passed,以及(2)如何取消嵌套CSV文件的列。

2 个答案:

答案 0 :(得分:2)

我可以通过几个步骤看到如何做到这一点:

sudo a2enmod expires
Enabling module expires.
Run '/etc/init.d/apache2 restart' to activate new configuration!

结果:

import numpy as np, pandas as pd
df['total'] = df['passed'].astype(int)
ldf = pd.pivot_table(df,index=['sponsor','sponsor_class'],columns='year',
                     values=['total'],aggfunc=len) # total counts
rdf = pd.pivot_table(df,index=['sponsor','sponsor_class'],columns='year',
                     values=['total'],aggfunc=np.sum) # number passed 
cdf = pd.concat([ldf,rdf],axis=1) # combine horizontally
cdf.columns = cdf.columns.get_level_values(0) # flatten index
cdf.reset_index(inplace=True)
columns = ['sponsor','sponsor_class']
yrs = sorted(df['year'].unique())
columns.extend(['{}_total'.format(yr) for yr in yrs])
columns.extend(['{}_passed'.format(yr) for yr in yrs])
cdf.columns = columns

最后:

>>> cdf
  sponsor sponsor_class  2012_total  2013_total  2012_passed  2013_passed
0  A71991      Industry           1           2            1            1
1  A81001           NIH           1           1            1            1

答案 1 :(得分:2)

# set index to prep for unstack
df1 = df.set_index(['sponsor', 'sponsor_class', 'year']).astype(int)

# groupby all the stuff in the index
gb = df1.groupby(level=[0, 1, 2]).passed

# use agg to get sum and count    
# swaplevel and sort_index to get stuff sorted out
df2 = gb.agg({'passed': 'sum', 'total': 'count'}) \
          .unstack().swaplevel(0, 1, 1).sort_index(1)

# collapse multiindex into index
df2.columns = df2.columns.to_series().apply(lambda x: '{}_{}'.format(*x))

print df2.reset_index().to_csv(index=None)


sponsor,sponsor_class,2012_passed,2012_total,2013_passed,2013_total
A71991,Industry,1,1,1,2
A81001,NIH,1,1,1,1