Более эффективный / упрощенный расчет скользящего окна данных в Python - PullRequest
1 голос
/ 17 апреля 2020

Мой мультииндекс df выглядит так:

     Day 1        Day 2       Day 3       Day 4
     Var 1  Var2  Var1  Var2  Var1  Var2  Var1  Var2
A    1      2     3     4     5     6     7     8
B    9      10    11    12    13    14    15    16

... который я хочу преобразовать в сменный трехдневный df, например:

     Day -2       Day -1      Day 0        
     Var 1  Var2  Var1  Var2  Var1  Var2  
A    1      2     3     4     5     6     
B    9      10    11    12    13    14    
A    3      4     5     6     7     8
B    11     12    13    14    15    16

.. .с двумя сменами windows (день 1-3 и день 2-4) по 3 дня каждый. У меня пока есть рабочее решение с for-loop, которое зацикливается на все дни и все строки. Поскольку это занимает много времени: есть ли эффективный способ сделать это?

1 Ответ

0 голосов
/ 17 апреля 2020

Вы можете попытаться добавить последние столбцы n-1 к первым столбцам n-1, а затем изменить имя столбца:

def sub_n_days(col_name, n):
    return "Day {}".format(int(col_name.split(" ")[-1])-1)

out = df[days[:-1]].append(df[days[1:]]
                                .rename(columns=lambda x: sub_n_days(x, 1),
                                        level=0)) \
                   .rename(columns=lambda x: sub_n_days(x, 3), level=0)

Пояснения

  1. Определение функции для вычитания n дней для данного имени столбца. Вот простой. Я позволю вам улучшить его в соответствии с вашими потребностями.
# col_name is the column name and "n" the number of days to subtract
def sub_n_days(col_name, n):
    return "Day {}".format(int(col_name.split(" ")[-1])-1)

Сохранить имена столбцов первого уровня, используя days = df.columns.levels[0]

Выберите n-1 первые столбцы, используя df[days[:-1]]

Выберите столбцы n-1 last , используя df[days[1:]]

Переименуйте последний столбец n-1, вычитая один день. Мы используем rename и используем параметры столбца с лямбда-функцией. Мы также указываем используемый уровень (здесь уровень 0).

df[days[1:]].rename(columns=lambda x: sub_n_days(x, 1), level=0)

Затем мы добавляем результат из 3 и 5 вместе, используя pd.append:

df[days[:-1]].append(df[days[1:]].rename(columns=lambda x: sub_n_days(x, 1),
                                        level=0))
На шаге 5 мы переименовываем столбцы с помощью rename В последний раз мы переименовываем индекс с использованием rename

Полный код

# import modules
import numpy as np
import pandas as pd

# create dummy dataframe
col_1 = ["Day {}".format(i + 1) for i in range(9)]
col_2 = ['Var1', 'Var2']
col = [(c1, c2) for c1 in col_1 for c2 in col_2]
df = pd.DataFrame(np.arange(0, 36).reshape(2,18), columns=pd.MultiIndex.from_tuples(col))
print(df)
#   Day 1      Day 2      Day 3      Day 4      Day 5      Day 6      Day 7      Day 8      Day 9
#    Var1 Var2  Var1 Var2  Var1 Var2  Var1 Var2  Var1 Var2  Var1 Var2  Var1 Var2  Var1 Var2  Var1 Var2
# 0     0    1     2    3     4    5     6    7     8    9    10   11    12   13    14   15    16   17
# 1    18   19    20   21    22   23    24   25    26   27    28   29    30   31    32   33    34   35

# Colect days columns names
days = df.columns.levels[0]

# Define our own function to substract days of a given column name
def sub_n_days(col_name, n):
    return "Day {}".format(int(col_name.split(" ")[-1])-1)

# Apply the computation
out = df[days[:-1]].append(df[days[1:]]
                                .rename(columns=lambda x: sub_n_days(x, 1),
                                        level=0)) \
                   .rename(columns=lambda x: sub_n_days(x, 3), level=0) \
                   .rename(index={0: "A", 1: "B"})
print(out)
#   Day 0      Day 1      Day 2      Day 3      Day 4      Day 5      Day 6      Day 7
#    Var1 Var2  Var1 Var2  Var1 Var2  Var1 Var2  Var1 Var2  Var1 Var2  Var1 Var2  Var1 Var2
# A     0    1     2    3     4    5     6    7     8    9    10   11    12   13    14   15
# B    18   19    20   21    22   23    24   25    26   27    28   29    30   31    32   33
# A     2    3     4    5     6    7     8    9    10   11    12   13    14   15    16   17
# B    20   21    22   23    24   25    26   27    28   29    30   31    32   33    34   35
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...