Python добавить столбцы в DataFame с помощью скользящего окна на основе 3 предыдущих строк - PullRequest
1 голос
/ 01 мая 2020

У меня есть такой фрейм данных:

original = pd.DataFrame(np.random.randint(0,100,size=(10, 3)), columns=["P1_day", "P1_week", "P1_month"])
print(original)

   P1_day  P1_week  P1_month
0      50       17        55
1      45        3        10
2      93       79        84
3      99       38        33
4      44       35        35
5      25       43        87
6      38       88        56
7      20       66         6
8       4       23         6
9      39       75         3

Мне нужно сгенерировать новый фрейм данных, начиная с 3-й строки original фрейма данных, и добавить новые 9 столбцов на основе скользящего окна, определенного как 3 предыдущих строки с соответствующими префиксы: [_0, _1, _2]. Итак, это строки с индексом [0,1,2] из original dataframe. Например, следующие 3 столбца будут из original.iloc[0], а следующие 3 столбца будут из original.iloc[1], а последние 3 столбца будут из original.iloc[2]

. решить это следующим кодом:

    subset_shifted = original[["P1_day", "P1_week", "P1_month"]].shift(3)
    subset_shifted.columns = ["P1_day_0", "P1_week_0", "P1_month_0"]
    original_ = pd.concat([original, subset_shifted], axis = 1)
    print(original_)

В результате у меня есть 3 дополнительных столбца со значением из предыдущей строки 0:

   P1_day  P1_week  P1_month  P1_day_0  P1_week_0  P1_month_0
0      50       17        55       NaN        NaN         NaN
1      45        3        10       NaN        NaN         NaN
2      93       79        84       NaN        NaN         NaN
3      99       38        33      50.0       17.0        55.0
4      44       35        35      45.0        3.0        10.0
5      25       43        87      93.0       79.0        84.0
6      38       88        56      99.0       38.0        33.0
7      20       66         6      44.0       35.0        35.0
8       4       23         6      25.0       43.0        87.0
9      39       75         3      38.0       88.0        56.0

В следующей итерации я сделал shift(2) с тем же подходом и получил столбцы от original.iloc[1]. На последней итерации я сделал shift(1) и получил ожидаемый результат с учетом:

 result = original_.iloc[3:]

   P1_day  P1_week  P1_month  P1_day_0  P1_week_0  P1_month_0  P1_day_1  P1_week_1  P1_month_1  P1_day_2  P1_week_2  P1_month_2
3      99       38        33      50.0       17.0        55.0      45.0        3.0        10.0      93.0       79.0        84.0
4      44       35        35      45.0        3.0        10.0      93.0       79.0        84.0      99.0       38.0        33.0
5      25       43        87      93.0       79.0        84.0      99.0       38.0        33.0      44.0       35.0        35.0
6      38       88        56      99.0       38.0        33.0      44.0       35.0        35.0      25.0       43.0        87.0
7      20       66         6      44.0       35.0        35.0      25.0       43.0        87.0      38.0       88.0        56.0
8       4       23         6      25.0       43.0        87.0      38.0       88.0        56.0      20.0       66.0         6.0
9      39       75         3      38.0       88.0        56.0      20.0       66.0         6.0       4.0       23.0         6.0

Вопрос: есть ли способ решить эту задачу с лучшим подходом, как я описал? Спасибо.

1 Ответ

1 голос
/ 01 мая 2020

Если вам не нужны все эти дополнительные фреймы данных, вы можете просто добавить новые столбцы в свой оригинальный файл:

import pandas as pd
import numpy as np

original = pd.DataFrame(
    np.random.randint(0,100,size=(10, 3)), 
    columns=["P1_day", "P1_week", "P1_month"],
)

original[
    ["P1_day_0", "P1_week_0", "P1_month_0"]
] = original[
    ["P1_day", "P1_week", "P1_month"]
].shift(3)

print(original)

output:

   P1_day  P1_week  P1_month  P1_day_0  P1_week_0  P1_month_0
0       2       35        26       NaN        NaN         NaN
1      99        4        96       NaN        NaN         NaN
2       4       67         6       NaN        NaN         NaN
3      76       33        31       2.0       35.0        26.0
4      84       60        98      99.0        4.0        96.0
5      57        1        58       4.0       67.0         6.0
6      35       70        96      76.0       33.0        31.0
7      81       32        39      84.0       60.0        98.0
8      25        4        38      57.0        1.0        58.0
9      83        4        60      35.0       70.0        96.0

python ссылка на пример для репетитора

Редактировать: OP задал следующий вопрос:

да, для первого ряда это имеет смысл. Но моя задача состоит в том, чтобы добавить первые 3 строки с индексом 0-1-2 в виде новых 9 столбцов для соответствующих строк, начинающихся с 3-го индекса. В вашей выходной строке с индексом 1-й не добавляется 3-й ряд, как 3 столбца. Поэтому в моем коде я использовал итеративно shift (2) и shift (1).

Вот как это можно сделать итеративно:

import pandas as pd
import numpy as np

original = pd.DataFrame(
    np.random.randint(0,100,size=(10, 3)), 
    columns=["P1_day", "P1_week", "P1_month"],
)

for shift, n in ((3,0),(2,1),(1,2)):
    original[
        [f"P1_day_{n}", f"P1_week_{n}", f"P1_month_{n}"]
    ] = original[
        ["P1_day", "P1_week", "P1_month"]
    ].shift(shift)

pd.set_option('display.max_columns', None)
print(original.iloc[3:])

Вывод:

   P1_day  P1_week  P1_month  P1_day_0  P1_week_0  P1_month_0  P1_day_1  \
3      58       43        74      26.0       56.0        82.0      56.0   
4      44       27        40      56.0       87.0        38.0      31.0   
5       2       90         4      31.0       32.0        87.0      58.0   
6      90       70         6      58.0       43.0        74.0      44.0   
7       1       31        57      44.0       27.0        40.0       2.0   
8      96       22        69       2.0       90.0         4.0      90.0   
9      13       98        47      90.0       70.0         6.0       1.0   

   P1_week_1  P1_month_1  P1_day_2  P1_week_2  P1_month_2  
3       87.0        38.0      31.0       32.0        87.0  
4       32.0        87.0      58.0       43.0        74.0  
5       43.0        74.0      44.0       27.0        40.0  
6       27.0        40.0       2.0       90.0         4.0  
7       90.0         4.0      90.0       70.0         6.0  
8       70.0         6.0       1.0       31.0        57.0  
9       31.0        57.0      96.0       22.0        69.0

python ссылка преподавателя

Редактировать 2: Не делать здесь никаких предположений, но если ваша конечная цель - получить что-то вроде 4-периодной скользящей средней от данные во всех этих новых столбцах, тогда они могут вам вообще не понадобиться. Вы можете использовать pandas .DataFrame.rolling вместо:

import pandas as pd
import numpy as np

original = pd.DataFrame(
    np.random.randint(0,100,size=(10, 3)), 
    columns=["P1_day", "P1_week", "P1_month"],
)

original[
    ["P1_day_4PMA", "P1_week_4PMA", "P1_month_4PMA"]
] = original[
    ["P1_day", "P1_week", "P1_month"]
].rolling(4).mean()

pd.set_option('display.max_columns', None)
print(original.iloc[3:])

Вывод:

   P1_day  P1_week  P1_month  P1_day_4PMA  P1_week_4PMA  P1_month_4PMA
3       1       13        48        31.25         38.00          55.00
4      10        4        40        22.00         21.00          45.75
5       7       76         0         5.50         23.75          37.00
6       5       69         9         5.75         40.50          24.25
7      63       31        82        21.25         45.00          32.75
8      26       67        22        25.25         60.75          28.25
9      89       41        40        45.75         52.00          38.25

еще python ссылка для репетитора

...