【问题标题】:Using pct_change with multiindex groupby将 pct_change 与多索引 groupby 一起使用
【发布时间】:2023-03-04 03:24:01
【问题描述】:

我正在尝试在 groupby 的结果上使用 pct_change 来计算许多不同项目之间的价值变化。

我的数据结构如下:

import numpy as np
arrays = [np.array([1,2,3,4,1,2,3,4]),np.array(['bar', 'bar', 'bar', 'bar', 'foo', 'foo', 'foo', 'foo'])]
s = pd.Series(np.array([100,101,102,103,200,201,202,203]), index=arrays)
s.name='values'
df = pd.DataFrame(s, index=arrays).sort_index()
df.index.names =['day','symbol']

我需要计算每天每个符号的百分比变化。当我运行这样的事情时:

df.groupby(level='symbol').values.diff()

我得到了正确的输出。但是当我运行这个时:

df.groupby(level='symbol').values.pct_change()

它返回错误的结果(比较 bar 和 foo)

我可以通过像这样包装一个 lambda 来得到我正在寻找的东西:

my_func = lambda x: x.pct_change()
df.groupby(level='symbol').values.apply(my_func)

或通过这样做:

df.groupby(level='symbol').values.diff() / df.groupby(level='symbol').values.shift(1)

所以我真的只是想了解 pct_change 与其他 pandas 方法的行为差异的原因。

【问题讨论】:

  • 这很有趣。不知道这是否是一个错误。
  • @ScottBoston,这对我来说似乎是一个错误......

标签: pandas pandas-groupby


【解决方案1】:

对于 pandas 0.24.2 上的多索引数据帧,此解决方案对我有用:

pd.__version__

'0.24.2'


df.groupby(level='symbol')['values'].pct_change()


    day  symbol
1    bar            NaN
     foo            NaN
2    bar       0.010000
     foo       0.005000
3    bar       0.009901
     foo       0.004975
4    bar       0.009804
     foo       0.004950
Name: values, dtype: float64

【讨论】:

    【解决方案2】:

    看起来我们必须使用 .apply() 才能将它与多索引 DF 一起使用:

    In [61]: df.groupby(level='symbol')['values'].apply(lambda x: x.pct_change())
    Out[61]:
    day  symbol
    1    bar            NaN
         foo            NaN
    2    bar       0.010000
         foo       0.005000
    3    bar       0.009901
         foo       0.004975
    4    bar       0.009804
         foo       0.004950
    Name: values, dtype: float64
    

    PS 这对我来说似乎是一个错误 - IMO 在按多索引级别之一分组时它无法正常工作:

    In [101]: g = df.groupby(level='symbol')
    
    In [102]: g.values.pct_change??
    Signature: g.values.pct_change(periods=1, fill_method='pad', limit=None, freq=None)
    Source:
        def pct_change(self, periods=1, fill_method='pad', limit=None, freq=None):
            """Calculate percent change of each value to previous entry in group"""
            filled = getattr(self, fill_method)(limit=limit)
            shifted = filled.shift(periods=periods, freq=freq)
    
            return (filled / shifted) - 1
    File:      c:\users\max\anaconda3_5.0\envs\py36\lib\site-packages\pandas\core\groupby\groupby.py
    Type:      method
    

    复制代码:

    In [103]: filled = g['values'].pad(limit=None)
    
    In [104]: shifted = filled.shift(periods=1, freq=None)
    
    In [105]: (filled / shifted) - 1
    Out[105]:
    day  symbol
    1    bar            NaN
         foo       1.000000
    2    bar      -0.495000
         foo       0.990099
    3    bar      -0.492537
         foo       0.980392
    4    bar      -0.490099
         foo       0.970874
    Name: values, dtype: float64
    

    我建议检查Pandas-Issues上是否已经存在此类问题,如果尚不存在则打开一个新问题...

    【讨论】:

      猜你喜欢
      • 2020-09-09
      • 2017-03-09
      • 1970-01-01
      • 2011-12-14
      • 1970-01-01
      • 1970-01-01
      • 2020-11-10
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多