2014-08-27 168 views
3

我有一个从数据透视表创建一个数据帧,看起来与此类似:的总和除以多指标列创建百分比

import pandas as pd 
d = {('company1', 'False Negative'): {'April- 2012': 112.0, 'April- 2013': 370.0, 'April- 2014': 499.0, 'August- 2012': 431.0, 'August- 2013': 496.0, 'August- 2014': 221.0}, 
('company1', 'False Positive'): {'April- 2012': 0.0, 'April- 2013': 544.0, 'April- 2014': 50.0, 'August- 2012': 0.0, 'August- 2013': 0.0, 'August- 2014': 426.0}, 
('company1', 'True Positive'): {'April- 2012': 0.0, 'April- 2013': 140.0, 'April- 2014': 24.0, 'August- 2012': 0.0, 'August- 2013': 0.0,'August- 2014': 77.0}, 
('company2', 'False Negative'): {'April- 2012': 112.0, 'April- 2013': 370.0, 'April- 2014': 499.0, 'August- 2012': 431.0, 'August- 2013': 496.0, 'August- 2014': 221.0}, 
('company2', 'False Positive'): {'April- 2012': 0.0, 'April- 2013': 544.0, 'April- 2014': 50.0, 'August- 2012': 0.0, 'August- 2013': 0.0, 'August- 2014': 426.0}, 
('company2', 'True Positive'): {'April- 2012': 0.0, 'April- 2013': 140.0, 'April- 2014': 24.0, 'August- 2012': 0.0, 'August- 2013': 0.0,'August- 2014': 77.0},} 

df = pd.DataFrame(d) 

       company1 company2 
       FN FP TP FN FP TP 
April- 2012  112 0 0 112 0 0 
April- 2013  370 544 140 370 544 140 
April- 2014  499 50 24 499 50 24 
August- 2012 431 0 0 431 0 0 
August- 2013 496 0 0 496 0 0 
August- 2014 221 426 77 221 426 77 

我期待迭代在多指标柱的上部水平以每个公司的总和来划分以创建百分比:

   company1  company2 
       FN FP TP FN FP TP 
April- 2012  1 0 0 1 0 0 
April- 2013  .35 .51 .13 .35 .51 .13 
April- 2014  .87 .09 .03 .87 .09 .03 
etc. 

我不知道公司名称。这是一个问题的变化昨天问:Summing multiple columns with multiindex columns

+1

只是被昨天的答案的结果除? – joris 2014-08-27 15:12:26

+0

是的,这就是问题所在。如何做到这一点?我无法弄清楚如何排列它们而不会产生错误。 – DataSwede 2014-08-27 15:14:22

+0

相关:http://stackoverflow.com/questions/13940753/aligning-dataframes-with-same-columns-different-index-levels – 2014-08-27 19:01:42

回答

4

您可以通过使用div方法的总和除以(与您可以指定相匹配的水平):

df.div(df.sum(axis=1, level=0), level=0) 
+0

这是绝对完美的。再次感谢! – DataSwede 2014-08-27 15:17:59

1

,边将通过里斯作品很好,我想补充一点,Multiindex有更多级别时就不会工作。这里是我的解决方案部分基于StackOverflow文章(Normalize DataFrame by group)和熊猫文档(http://pandas.pydata.org/pandas-docs/stable/groupby.html)。

d = { 
('X', 'company1', 'False Negative'): {'April- 2012': 112.0, 'April- 2013': 370.0, 'April- 2014': 499.0, 'August- 2012': 431.0, 'August- 2013': 496.0, 'August- 2014': 221.0}, 
('X', 'company1', 'False Positive'): {'April- 2012': 0.0, 'April- 2013': 544.0, 'April- 2014': 50.0, 'August- 2012': 0.0, 'August- 2013': 0.0, 'August- 2014': 426.0}, 
('X', 'company1', 'True Positive'): {'April- 2012': 0.0, 'April- 2013': 140.0, 'April- 2014': 24.0, 'August- 2012': 0.0, 'August- 2013': 0.0,'August- 2014': 77.0}, 
('X', 'company2', 'False Negative'): {'April- 2012': 112.0, 'April- 2013': 370.0, 'April- 2014': 499.0, 'August- 2012': 431.0, 'August- 2013': 496.0, 'August- 2014': 221.0}, 
('X', 'company2', 'False Positive'): {'April- 2012': 0.0, 'April- 2013': 544.0, 'April- 2014': 50.0, 'August- 2012': 0.0, 'August- 2013': 0.0, 'August- 2014': 426.0}, 
('X', 'company2', 'True Positive'): {'April- 2012': 0.0, 'April- 2013': 140.0, 'April- 2014': 24.0, 'August- 2012': 0.0, 'August- 2013': 0.0,'August- 2014': 77.0}, 
('Y','company1', 'False Negative'): {'April- 2012': 112.0, 'April- 2013': 370.0, 'April- 2014': 499.0, 'August- 2012': 431.0, 'August- 2013': 496.0, 'August- 2014': 221.0}, 
('Y','company1', 'False Positive'): {'April- 2012': 0.0, 'April- 2013': 544.0, 'April- 2014': 50.0, 'August- 2012': 0.0, 'August- 2013': 0.0, 'August- 2014': 426.0}, 
('Y','company1', 'True Positive'): {'April- 2012': 0.0, 'April- 2013': 140.0, 'April- 2014': 24.0, 'August- 2012': 0.0, 'August- 2013': 0.0,'August- 2014': 77.0}, 
('Y','company2', 'False Negative'): {'April- 2012': 112.0, 'April- 2013': 370.0, 'April- 2014': 499.0, 'August- 2012': 431.0, 'August- 2013': 496.0, 'August- 2014': 221.0}, 
('Y','company2', 'False Positive'): {'April- 2012': 0.0, 'April- 2013': 544.0, 'April- 2014': 50.0, 'August- 2012': 0.0, 'August- 2013': 0.0, 'August- 2014': 426.0}, 
('Y','company2', 'True Positive'): {'April- 2012': 0.0, 'April- 2013': 140.0, 'April- 2014': 24.0, 'August- 2012': 0.0, 'August- 2013': 0.0,'August- 2014': 77.0}, 
} 

df = pd.DataFrame(d) 
# extrapolation of original method: not working! 
# df.div(df.sum(axis=1,level=[0,1]), level=[0,1]) # does not work 

# alternative 1: replicating the sums for each company to fit the number of columns using numpy 
df.div(np.repeat(df.sum(axis=1,level=[0,1]).values, 3, axis=1), axis=1) 

# alternative 2: stacking, grouping, transforming and unstacking 
df.columns.names = ['top', 'company', 'result'] # naming column levels for convenience 
df.\ 
    stack(["top", "company", "result"]).\ 
    groupby(level=[0,1,2]).\ 
    transform(lambda x: (x/x.sum(axis=0))).\ 
    unstack(["top", "company", "result"])