2014-08-27 2 views
3

У меня есть dataframe, который создается из сводной таблицы, и выглядит примерно так:Разделив мультииндексных столбцы по сумме создать проценты

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

+0

Да, это вопрос. Как это сделать? Я не могу понять, как выстроить их, не создавая ошибок. – DataSwede

+0

related: http://stackoverflow.com/questions/13940753/aligning-dataframes-with-same-columns-different-index-levels –

ответ

4

можно разделить на сумму, используя div метод (с этим можно указать уровень, соответствующий):

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

Это было абсолютно идеально. Еще раз спасибо! – DataSwede

1

Хотя решение по JORIS работ Я хочу добавить, что это не сработает, как только Multiindex будет иметь больше уровней. Вот мои решения частично основаны на сообщении StackOverflow (Normalize DataFrame by group) и документах Pandas (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"]) 
Смежные вопросы