Создайте скользящее среднее в кадре данных до заданного значения

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

month val1 val2 val3
1      2    3    5
2      3    4    7
3      5    1    2
4      7    4    3
5      2    6    4
6      2    2    2

Последний месяц в моем исходном столбце здесь равен 6, но это может быть что угодно от месяца 1 до месяца 12. Я хочу рассчитать скользящее среднее на основе последних 2 значений для каждого столбца val до месяца 12. Чтобы получить что-то вроде этого:

month val1 val2 val3
1      2    3    5
2      3    4    7
3      5    1    2
4      7    4    3
5      2    6    4
6      2    2    2
7      2    4    3
8      2    3    2.5
9      2   3.5   2.75
10     2   3.25  2.63
11     2   3.38  2.69
12     2   3.32  2.66

person Arlowest    schedule 12.07.2020    source источник
comment
Является ли месяц индексом?   -  person Derek O    schedule 12.07.2020
comment
Всегда ли столбец месяца в последовательном порядке?   -  person Shubham Sharma    schedule 12.07.2020
comment
месяц - это отдельный столбец, всегда в последовательном порядке   -  person Arlowest    schedule 12.07.2020


Ответы (2)


Основная проблема заключается в том, что добавление строк в фреймы данных - очень неэффективный процесс (т.е. создание новой серии фреймов данных на каждой итерации и добавление их к исходному фрейму данных будет чрезвычайно затратным).

Вероятно, лучший способ сделать это - создать массив из фрейма данных, выполнить там скользящие вычисления и преобразовать результат в новый фрейм данных.

import pandas as pd
import numpy as np 

# create dataframe with the first month removed to show the solution is generalizable
df = pd.DataFrame({'month':[2,3,4,5,6],'val1':[3,5,7,2,2],'val2':[4,1,4,6,2],'val3':[7,2,3,4,2]})

df
   month  val1  val2  val3
0      2     3     4     7
1      3     5     1     2
2      4     7     4     3
3      5     2     6     4
4      6     2     2     2

# extract values of the dataframe as numpy and perform rolling operations
# separate out months from other columns
array_values = df.drop(columns = 'month').values

# loop from most recent month to month 12 
for month in range(df.month.iloc[-1],12):
    array_values = np.append(array_values, np.apply_along_axis(np.mean, 0,array_values[-2:]).reshape(1,3), axis = 0)

array_months = np.append(df.month.values, np.arange(df.month.values[-1]+1,13,1))
array_months = array_months.reshape(len(array_months),1)
array_values = np.append(array_months, array_values, axis = 1)

new_df = pd.DataFrame(data = array_values, columns = df.columns)
new_df.month = new_df.month.astype('int')

Вывод:

new_df
    month  val1    val2     val3
0       2   3.0  4.0000  7.00000
1       3   5.0  1.0000  2.00000
2       4   7.0  4.0000  3.00000
3       5   2.0  6.0000  4.00000
4       6   2.0  2.0000  2.00000
5       7   2.0  4.0000  3.00000
6       8   2.0  3.0000  2.50000
7       9   2.0  3.5000  2.75000
8      10   2.0  3.2500  2.62500
9      11   2.0  3.3750  2.68750
10     12   2.0  3.3125  2.65625
person Derek O    schedule 12.07.2020

Определите следующую функцию, генерирующую строки для оставшейся части текущего года на основе последних 2 строк:

def getRest(last2):
    last2 = last2.set_index('month')
    lastMonth = last2.index[1]
    rv = []
    for mnth in range(lastMonth, 12):
        newRow = last2.mean()
        newRow.name = mnth + 1
        rv.append(newRow)
        last2 = last2.drop([mnth - 1])
        last2 = last2.append(newRow)
    return rv

Затем вызовите его следующим образом, объединив с исходным DataFrame:

pd.concat([df, pd.concat(getRest(df.iloc[-2:]), axis=1).T.reset_index()
    .rename(columns={'index': 'month'})], ignore_index=True)

Результат:

    month  val1    val2     val3
0       1   2.0  3.0000  5.00000
1       2   3.0  4.0000  7.00000
2       3   5.0  1.0000  2.00000
3       4   7.0  4.0000  3.00000
4       5   2.0  6.0000  4.00000
5       6   2.0  2.0000  2.00000
6       7   2.0  4.0000  3.00000
7       8   2.0  3.0000  2.50000
8       9   2.0  3.5000  2.75000
9      10   2.0  3.2500  2.62500
10     11   2.0  3.3750  2.68750
11     12   2.0  3.3125  2.65625

Если хотите, сохраните этот результат либо под исходной переменной, либо под другой.

person Valdi_Bo    schedule 12.07.2020