2016-07-25 58 views
4

我是熊猫新手。我有赞助商,公司采取考试的数据帧:熊猫:通过两个不同的维度创建数据透视表?

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']) 

但是,这给了我一个空的数据帧。

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

UPDATE:取得了一些进展:

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
# 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 
+0

这是惊人的,谢谢! – Richard

2

我可以看到如何做到这一点在相当多的步骤:

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 

最后:

cdf.to_csv('/path/to/file.csv',index=False)