У меня есть датафрейм:
import pandas as pd
df = pd.DataFrame([['A', 'G1', '2019-01-01', 11],
['A', 'G1', '2019-01-02', 12],
['A', 'G1', '2019-01-04', 14],
['B', 'G2', '2019-01-01', 11],
['B', 'G2', '2019-01-03', 13],
['B', 'G2', '2019-01-06', 16]],
columns=['cust', 'group', 'date', 'val'])
df
df = df.groupby(['cust', 'group', 'date']).sum()
df
Фрейм данных сгруппирован, и теперь я хотел бы вычислить pct_change
, но только если есть предыдущая дата.
Если я сделаю это так:
df['pct'] = df.groupby(['cust', 'group']).val.pct_change()
df
Я получу pct_change
, но без учета пропущенных дат.
Например, в группе ('A', 'G1')
, pct
для даты 2019-01-04
должно быть np.nan
, поскольку нет (предыдущей) даты 2019-01-03
.
Может быть, решением было бы сделать повторную выборку по дням, где каждая новая строка будет иметь np.nan
как val
, а затем сделать pct_change
.
Я пытался использовать df.resample('1D', level=2)
, но я получаю сообщение об ошибке:
TypeError: Действителен только с DatetimeIndex, TimedeltaIndex или PeriodIndex, но получил экземпляр MultiIndex
Для группы ('B', 'G2')
все pct_change
должны быть np.nan
, поскольку ни одна из строк не имеет предыдущей даты.
Ожидаемый результат:
Как рассчитать pct_change
с учетом пропущенных дат?
Решение:
new_df = pd.DataFrame()
for x, y in df.groupby(['cust', 'group']):
resampled=y.set_index('date').resample('D').val.mean().to_frame().rename({'val': 'resamp_val'}, axis=1)
resampled = resampled.join(y.set_index('date')).fillna({'cust':x[0],'group':x[1]})
resampled['resamp_val_pct'] = resampled.resamp_val.pct_change(fill_method=None)
new_df = pd.concat([new_df, resampled])
new_df = new_df[['cust', 'group', 'val', 'resamp_val', 'resamp_val_pct']]
new_df