2013-10-07 4 views
1

Предположим, у меня есть следующий набор данныхНакопительное сумма с отсутствующими категорий в панд

df_dict = ({'unit' : [1, 1, 1, 2, 2, 2], 'cat' : [1, 2, 3, 1, 2, 4], 
      'count' : [8, 3, 2, 2, 8, 7] }) 
df = pd.DataFrame(df_dict) 

df.set_index('unit', inplace = True) 

который выглядит следующим образом:

cat count 
unit   
1 1 8 
1 2 3 
1 3 2 
2 1 2 
2 2 8 
2 4 7 

Отсчет дает частоту, в которой различные категории, где наблюдаемые в блоке. То, что я хотел бы получить, - это совокупная частота четырех категорий для каждой единицы. Обратите внимание, что категория 4 отсутствует из блока 1 и 3-й категории отсутствует блок 2.

Таким образом, конечный результат будет

для блока 1:

[8/13, 11/13, 13/13, 13/13] 

и для блока 2:

[2/17, 10/17, 10/17, 17/17] 

Я знаю, как получить накопленную сумму с groupby и cumsum, но затем блок 1, например, не имеет значения для недостающей категории 4.

Спасибо за ваше время!

ответ

2
import pandas as pd 


df_dict = ({'unit' : [1, 1, 1, 2, 2, 2], 'cat' : [1, 2, 3, 1, 2, 4], 
      'count' : [8, 3, 2, 2, 8, 7] }) 
df = pd.DataFrame(df_dict) 

df.set_index('unit', inplace = True)  

cumsum_count = df.groupby(level=0).apply(lambda x: pd.Series(x['count'].cumsum().values, index=x['cat'])) 
# unit cat 
# 1  1  8 
#  2  11 
#  3  13 
# 2  1  2 
#  2  10 
#  4  17 
# dtype: int64 

cumsum_count = cumsum_count.unstack(level=1).fillna(method='ffill', axis=1) 
# cat 1 2 3 4 
# unit    
# 1  8 11 13 13 
# 2  2 10 10 17 

totals = df.groupby(level=0)['count'].sum() 
# unit 
# 1  13 
# 2  17 
# Name: count, dtype: int64 

cumsum_dist = cumsum_count.div(totals, axis=0) 
print(cumsum_dist) 

дает

cat   1   2   3 4 
unit         
1  0.615385 0.846154 1.000000 1 
2  0.117647 0.588235 0.588235 1 

Я действительно не знаю, как объяснить это решение - вероятно, потому, что я прибыл на него несколько serendipidously. Вдохновение пришли из Jeff's solution, который использовал

s.apply(lambda x: pd.Series(1, index=x)) 

связать значения с индексом. После того, как вы связали кумулятивный счет (значения), например. [8,11,13], с номерами cat (индекс), т.е. [1,2,3], вы в основном дома бесплатно. Остальные являются стандартными приложениями unstack, fillna, div и groupby.

+0

Спасибо, действительно хорошее решение !! Мне все равно нужно обернуть голову вокруг значений, связанных с вещью индекса ... Один быстрый вопрос: зачем вам нужно использовать '.values' в' cumsum(). Values'? Я не понимаю, что это делает. – cd98

+1

Внутри 'lambda' функция' x' является DataFrame. 'x ['count']. cumsum()' - это серия. У этой серии есть свой индекс, который я бы хотел заменить на 'x ['cat']'. Если мы используем 'pd.Series (x ['count']. Cumsum(), index = x ['cat'])', то возникает исключение 'ValueError: not reindex ...', потому что исходная серия имеет дубликат записи в его индексе - так что неясно, как сопоставить старый индекс с новым индексом. Каждая серия имеет атрибут 'values', который возвращает базовые данные в виде массива NumPy. Все, о чем мы заботимся, это данные, а не исходный индекс, поэтому я использовал '.values' для сбора данных. – unutbu

+0

Получил, спасибо! – cd98

Смежные вопросы