Я отслеживаю, в каком месяце произошло определенное событие. Если это не так, поле «месяц» является NaN. Стартовая таблица выглядит так:
+-------+----------+---------+
| Month | Category | Balance |
+-------+----------+---------+
| 1 | a | 100 |
| nan | a | 300 |
| 2 | a | 200 |
+-------+----------+---------+
Я пытаюсь создать кросс-таблицу следующим образом:
+-------+----------------------------------+
| Month | Category a - cumulative % amount |
+-------+----------------------------------+
| 1 | 0.16 |
| 2 | 0.50 |
+-------+----------------------------------+
В 1-м месяце событие произошло за 100/600, ie на 16% Во 2-м месяце событие произошло в совокупности для (100 + 200) / 600 = 50%, где 100 в 1-м месяце и 200 в 2-м.
Моя проблема связана с NaNs , Pandas автоматически удаляет NaN из любой групповой / сводной / кросс-таблицы. Я мог бы преобразовать поле месяца в строку, чтобы при группировке оно не удаляло NaN, но затем pandas сортирует по месяцу, как если бы это была строка, ie сортирует: 10, 48, 5, 6 .
Есть предложения?
Бит ниже работает, но кажется очень запутанным:
- Я конвертирую 'month' в строку
- Сделать кросс-таблицу
- Конвертировать месяц назад в число с плавающей точкой (можно ли сделать это, не перемещая индекс в столбец, а затем столбец обратно в индекс?)
- Сортировка снова
- Делать cumsum
Код:
import numpy as np
import pandas as pd
df = pd.DataFrame()
mylen = int(10e3)
df['ix'] = np.arange(0,mylen)
df['amount'] = np.random.uniform(10e3,20e3,mylen)
df['category'] = np.where( df['ix'] <=4000, 'a','b' )
df['month'] = np.random.uniform(3,48,mylen)
df['month'] = np.where( df['ix'] <=1000, np.nan, df['month'] )
df['month rounded'] = np.ceil(df['month'])
ct = pd.crosstab(df['month rounded'].astype(str) , df['category'], \
values = df['amount'] ,aggfunc = 'sum', margins = True ,\
normalize = 'columns', dropna = False)
# the index is 'month rounded'
ct = ct.reset_index()
ct['month rounded'] = ct['month rounded'].astype('float32')
ct = ct.sort_values('month rounded')
ct = ct.set_index('month rounded')
ct2 = ct.cumsum (axis = 0)