在系列结束时扩展pct_change的数据/收缩窗口

时间:2019-06-29 07:27:56

标签: python pandas pandas-groupby sliding-window

我正在尝试计算一系列变化的百分比变化(大于1的周期),并且在系列结束时出现窗口缩小的情况。

以下示例无法产生预期的结果:

    import pandas as pd
    import numpy as np

    labels = ['A', 'A', 'A', 'A', 'A', 'B', 'A', 'C', 'B', 'B', 'B', 'B', 'C', 'C', 'C', 'C', 'B']
    prices = [62, 55, 55, 74, 31, 77, 20, 21, 25, 30, 21, 35, 66, 12, 1, 2, 4]
    df = pd.DataFrame(data = {'label':labels,'price': price}, columns = ['label', 'price'])
    df['price_chg'] = df.groupby('label')['price'].transform(lambda x: x.pct_change(3, fill_method=None).shift(-3))
    df = df.iloc[np.lexsort((df.index, df['label'].values))]

df

        label   price   price_chg
    0   A       62      0.193548
    1   A       55      -0.436364
    2   A       55      -0.636364
    3   A       74      NaN
    4   A       31      NaN
    6   A       20      NaN
    5   B       77      -0.727273
    8   B       25      0.400000
    9   B       30      -0.866667
    10  B       21      NaN
    11  B       35      NaN
    16  B       4       NaN
    7   C       21      -0.952381
    12  C       66      -0.969697
    13  C       12      NaN
    14  C       1       NaN
    15  C       2       NaN

所需结果:


        label   price   price_chg
    0   A       62      0.193548
    1   A       55      -0.436364
    2   A       55      -0.636364
    3*  A       74      -0.729730
    4*  A       31      -0.354839
    6   A       20      NaN
    5   B       77      -0.727273
    8   B       25      0.400000
    9   B       30      -0.866667
    10* B       21      -0.809523
    11* B       35      -0.885714
    16  B       4       NaN
    7   C       21      -0.952381
    12  C       66      -0.969697
    13* C       12      -0.833333
    14* C       1       1.000000
    15  C       2       NaN

在期望的结果中,百分比变化计算继续超过组“ A”的索引2。因此,索引3和索引4的值计算如下:

    df.loc[3,['price_chg']] = float(df.loc[6,['price']] / df.loc[3,['price']] - 1)
    -0.729730
    df.loc[4,['price_chg']] = float(df.loc[6,['price']] / df.loc[4,['price']] - 1)
    -0.354839

对于索引10和11(标签“ B”)的值类似:

    df.loc[10,['price_chg']] = float(df.loc[16,['price']] / df.loc[10,['price']] - 1)
    -0.809523
    df.loc[11,['price_chg']] = float(df.loc[16,['price']] / df.loc[11,['price']] - 1)
    -0.885714

以及类似的标签“ C”。

我当时想做一个自定义的滑动窗口函数,或者一种将序列的最后一个值重复所需次数(虚拟扩展)的方法,但是我不熟悉如何完成此操作。由于我要处理大量pct_change()周期和大量数据,因此我认为自定义滑动窗口方法可能会更快,因此比扩展序列更可取。

谢谢!

1 个答案:

答案 0 :(得分:1)

我认为主要的问题是计算百分比然后进行平移会导致NaN填充极端值。

您的问题的一种解决方案是使用pandas.DataFrame.shift计算百分比:

df['price_chg'] = df.groupby('label')['price'].transform(
                  lambda x: (x.shift(-3).ffill(limit=2)-x)/x)

x.shift(-3).ffill(limit=2):在此表达式中,我们向后移动行,并用标签可用的最后一个值填充出现的nan值。我们的最大填充量将为两行,因为当我们向前填充时,最后一行将对应于period = 0(pct_change = 0),这是不希望的。

然后df将是:

> df

   label  price  price_chg
0      A     62   0.193548
1      A     55  -0.436364
2      A     55  -0.636364
3      A     74  -0.729730
4      A     31  -0.354839
6      A     20        NaN
5      B     77  -0.727273
8      B     25   0.400000
9      B     30  -0.866667
10     B     21  -0.809524
11     B     35  -0.885714
16     B      4        NaN
7      C     21  -0.952381
12     C     66  -0.969697
13     C     12  -0.833333
14     C      1   1.000000
15     C      2        NaN