#python #pandas
#python #pandas
Вопрос:
Предположим, у меня есть DataFrame
с MultiIndex
таким:
import pandas as pd
import numppy as np
iterables = [[1,2],['2011Q4','2012Q1','2012Q2','2012Q3','2012Q4','2013Q1','2013Q2','2013Q4']]
data = pd.DataFrame(np.random.random((16,1)), columns=['val'],
index=pd.MultiIndex.from_product(iterables,names=['id','date']))
Если я хочу создать задержку val
, я бы сделал это:
data['val_lag1'] = data.groupby(level=0)['val'].shift(1)
что дает
val val_lag1
id date
1 2011Q4 0.215183 NaN
2012Q1 0.929456 0.215183
2012Q2 0.171601 0.929456
2012Q3 0.387254 0.171601
2012Q4 0.805295 0.387254
2013Q1 0.592925 0.805295
2013Q2 0.446619 0.592925
2013Q4 0.962464 0.446619
2 2011Q4 0.723046 NaN
2012Q1 0.840808 0.723046
2012Q2 0.249003 0.840808
2012Q3 0.306059 0.249003
2012Q4 0.199025 0.306059
2013Q1 0.815567 0.199025
2013Q2 0.835140 0.815567
2013Q4 0.322251 0.835140
Однако, когда я пытаюсь сделать по существу что-то очень похожее, rolling()
это не работает, потому что оно дублирует один уровень индекса в процессе. То есть невозможно назначить
data['val_ma4'] = data.groupby(level=0)['val'].rolling(4).mean()
как могло бы показаться естественным / очевидным, потому data.groupby(level=0)['val'].rolling(4).mean()
что теперь имеет индекс третьего уровня:
id id date
1 1 2011Q4 NaN
2012Q1 NaN
2012Q2 NaN
2012Q3 0.466110
2012Q4 0.392576
2013Q1 0.408187
2013Q2 0.432501
2013Q4 0.600802
2 2 2011Q4 NaN
2012Q1 NaN
2012Q2 NaN
2012Q3 0.535583
2012Q4 0.463489
2013Q1 0.639357
2013Q2 0.683905
2013Q4 0.686587
Name: val, dtype: float64
Я могу избавиться от дополнительного уровня индекса, но почему он появляется и почему я должен это делать? Для меня не имеет смысла, что я должен это делать:
xx = data.groupby(level=0)['val'].rolling(4).mean()
data['val_ma4'] = xx.unstack().groupby(level=0).mean().stack()
Комментарии:
1. Быстрый поиск в Google показывает, что это ошибка с 2016 года. И предложения показывают, как использовать
apply
.
Ответ №1:
В этом случае вам нужно использовать apply()
:
data['val_ma4'] = data.groupby(level=0)['val'].apply(lambda x: x.rolling(4).mean())
И вы достигаете желаемого результата:
val val_lag1 val_ma4
id date
1 2011Q4 0.071332 NaN NaN
2012Q1 0.738045 0.071332 NaN
2012Q2 0.578402 0.738045 NaN
2012Q3 0.670338 0.578402 0.514529
2012Q4 0.595443 0.670338 0.645557
2013Q1 0.389000 0.595443 0.558296
2013Q2 0.632672 0.389000 0.571863
2013Q4 0.031375 0.632672 0.412123
2 2011Q4 0.860161 NaN NaN
2012Q1 0.337713 0.860161 NaN
2012Q2 0.480819 0.337713 NaN
2012Q3 0.167317 0.480819 0.461502
2012Q4 0.650774 0.167317 0.409156
2013Q1 0.197799 0.650774 0.374178
2013Q2 0.417418 0.197799 0.358327
2013Q4 0.705662 0.417418 0.492913
Комментарии:
1. Извините, я, наверное, не понял в своем вопросе, что скользящее среднее должно быть вычислено для каждой группы. Таким образом, для
id=2
значений, связанных с2011Q4
through2012Q2
, должно отсутствовать2. Я соответствующим образом обновил свой ответ, спасибо за разъяснение!