2016-04-24 134 views
-1

我想为索引#1(即水果和动物)和列的小计列(即2015和2016)添加小计行。大熊猫数据透视表索引和列的小计

对于小计列,我可以做这样的事情,但是对于每年运行这种类型的代码似乎效率不高(2015 & 2016)。有没有更好的办法?我不认为'利润率'会起作用,因为有多个小计。

df[('2015','2015_Total')] = df[('2015','1st')]+df[('2015','2nd')] 

对于小计行(例如,水果总数和动物总数),我不确定从哪里开始。

enter image description here

+0

你能否能够添加一段代码来生成数据帧,达到高达你需要帮助的点? – Abbas

回答

1

这是非常复杂的,因为你需要在columnsindex创建Multiindex

创建小计很容易 - 使用groupbysum。然后创建Multiindex并将concat新列更改为原始DataFrame。最后,你必须sort_index(I值前添加Total_正确排序):

print df 
       2015_____  2016_______  
        1st 2nd   1st 2nd 
Fruits Apple   10 9   11 10 
     Banana  20 22   21 20 
Animal Lion   5 3   2 1 
     Tiger   2 3   5 0 

df1 = df.groupby(level=0, axis=1).sum() 
print df1 
       2015_____ 2016_______ 
Fruits Apple   19   21 
     Banana   42   41 
Animal Lion   8   3 
     Tiger   5   5 

print df.columns.get_level_values(0).to_series().drop_duplicates().tolist() 
['2015_____', '2016_______'] 

#change index to multiindex 
new_columns = zip(df.columns.get_level_values(0).to_series().drop_duplicates().tolist(), 
        "Total_" + df1.columns.str[:4]) 
print new_columns 
[('2015_____', 'Total_2015'), ('2016_______', 'Total_2016')] 

df1.columns = pd.MultiIndex.from_tuples(new_columns) 
print df1 
       2015_____ 2016_______ 
       Total_2015 Total_2016 
Fruits Apple   19   21 
     Banana   42   41 
Animal Lion   8   3 
     Tiger   5   5 

df = pd.concat([df,df1], axis=1) 
df2 = df.groupby(level=0, sort=False).sum() 
print df2 
     2015_____  2016_______  2015_____ 2016_______ 
      1st 2nd   1st 2nd Total_2015 Total_2016 
Animal   7 6   7 1   13   8 
Fruits  30 31   32 30   61   62 

print df.index.levels[0][df.columns.labels[0]].to_series().drop_duplicates().tolist() 
['Animal', 'Fruits'] 

#change index to multiindex 
new_idx=zip(df.index.levels[0][df.columns.labels[0]].to_series().drop_duplicates().tolist(), 
      "Total_" + df2.index) 
print new_idx 
[('Animal', 'Total_Animal'), ('Fruits', 'Total_Fruits')] 

df2.index = pd.MultiIndex.from_tuples(new_idx) 
print df2 
        2015_____  2016_______  2015_____ 2016_______ 
          1st 2nd   1st 2nd Total_2015 Total_2016 
Animal Total_Animal   7 6   7 1   13   8 
Fruits Total_Fruits  30 31   32 30   61   62 

df = pd.concat([df,df2]) 
df = df.sort_index(axis=1).sort_index() 
print df 
        2015_____    2016_______    
          1st 2nd Total_2015   1st 2nd Total_2016 
Animal Lion     5 3   8   2 1   3 
     Tiger    2 3   5   5 0   5 
     Total_Animal   7 6   13   7 1   8 
Fruits Apple    10 9   19   11 10   21 
     Banana    20 22   42   21 20   41 
     Total_Fruits  30 31   61   32 30   62 
+0

谢谢!我认为你不是有意要在new_idx = zip(df.index.levels [0] [df.columns.labels [0]]中包含df.columns.labels [0] ...,对吗? –

+0

是的,我我认为你也可以在列中使用它,我必须使用这种方法,因为有问题 - 列表的值被交换了。Btw,[解决方案也使用标签](http://stackoverflow.com/questions/14189695) /复位指数换数据帧列)。 – jezrael