Python 带groupby()的函数以奇怪的方式更改索引

Python 带groupby()的函数以奇怪的方式更改索引,python,pandas,Python,Pandas,假设我有一个带有多索引的DataFrame,如下所示: 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

假设我有一个带有多索引的
DataFrame
,如下所示:

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)
xx = data.groupby(level=0)['val'].rolling(4).mean()
data['val_ma4'] = xx.unstack().groupby(level=0).mean().stack()
产生

                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
我可以去掉额外的索引级别,但为什么它会出现,为什么我必须这样做?我不认为我应该这样做:

data['val_lag1'] = data.groupby(level=0)['val'].shift(1)
xx = data.groupby(level=0)['val'].rolling(4).mean()
data['val_ma4'] = xx.unstack().groupby(level=0).mean().stack()

在这种情况下,您需要使用
apply()

并且您实现了所需的输出:

                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

谷歌(google)的一项快速调查显示,这是自2016年以来的一次重大变革。建议使用
apply
。对不起,我想我在问题中不清楚需要为每组计算移动平均值。因此,对于
id=2
而言,与
2011Q4
2012Q2
相关的值应该丢失。我已经相应地更新了我的答案,感谢您的澄清!