Расширить окно данных / сжатия для pct_change в конце ряда - PullRequest
0 голосов
/ 29 июня 2019

Я пытаюсь рассчитать процентное изменение (для периодов больше 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))]

ДФ

        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

В желаемом результате вычисление процентного изменения продолжается после индекса 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 () и большим количеством данных, я думаю, что подход с настраиваемым скользящим окном может быть более быстрым и, следовательно, более предпочтительным, чем расширение серии.

Thx!

1 Ответ

1 голос
/ 29 июня 2019

Я думаю, что основная проблема заключается в том, что при вычислении процента и последующем сдвиге значения, находящиеся на крайних значениях, заполняются 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, появляющиеся последним значением, доступным для метки. Наше максимальное заполнение будет состоять из двух строк, поскольку, поскольку мы выполняем прямое заполнение, последняя строка будет соответствовать периоду = 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
...