Python: numpy, pandas и выполнение операций над предыдущим значением массива (сглаженные средние): есть ли способ не использовать цикл FOR? EWMA?

1

ТБ, я не совсем уверен, как задать этот вопрос. У меня есть массив значений, и я ищу, чтобы сгладить среднее значение этих значений, продвигаясь вперед. В Excel процесс расчета:

  • average_val_1 = среднее значение средних значений через window_size
  • average_val_2 = (значение в местоположении window_size + 1 * window_size-1 + average_val_1)/window_size
  • average_val_3 = (значение в местоположении window_size + 2 * window_size-1 + average_val_2)/window_size

и т.д.

В pandas и numpy мой код для этого следующий

df = pd.DataFrame({'av':np.nan, 'values':np.random.rand(10)})
df = df[['values','av']]

window = 5
df['av'].iloc[5] = np.mean(df['values'][:5])

for i in range(window+1,len(df.index)):
  df['av'].iloc[i] = (df['values'].iloc[i] * (window-1) + df['av'].iloc[i-1])/window

Что возвращает:

    values      av
0   0.418498    NaN
1   0.570326    NaN
2   0.296878    NaN
3   0.308445    NaN
4   0.127376    NaN
5   0.381160    0.344305
6   0.239725    0.260641
7   0.928491    0.794921
8   0.711632    0.728290
9   0.319791    0.401491

Это значения, которые я ищу, но должен быть лучший способ, чем использовать для циклов. Я думаю, что ответ имеет какое-то отношение к использованию экспоненциально взвешенных скользящих средних, но я буду проклят, если смогу понять синтаксис, чтобы понять это.

Какие-либо предложения?

Теги:
pandas
numpy

1 ответ

0
Лучший ответ

вы можете использовать ewm, например:

window = 5
df['av'] = np.nan
df['av'].iloc[window] = np.mean(df['values'][:window])
df.loc[window:,'av'] = (df.loc[window:,'av'].fillna(df['values'])
                          .ewm(adjust=False, alpha=(window-1.)/window).mean())

и вы получите тот же результат, чем с петлей for. Для того, чтобы убедиться, что она работает, колонка "ау" должна быть nan иначе fillna с колонкой "значениями" не будет, а значение calculted в "ау" будет неправильно. Параметр alpha в ewm - это то, что помогает вам подсчитывать строку, которую вы вычисляете.

Примечание: хотя этот код работает как ваш, я бы рекомендовал взглянуть на эту строку в вашем коде:

df['av'].iloc[5] = np.mean(df['values'][:5])

Из-за исключения вершинной привязки при выполнении нарезки [:5] df['values'][:5]:

0    0.418498
1    0.570326
2    0.296878
3    0.308445
4    0.127376
Name: values, dtype: float64

поэтому я думаю, что вам нужно сделать df['av'].iloc[4] = np.mean(df['values'][:5]). Если вы согласитесь, то мое выше должно быть слегка изменено

df['av'].iloc[window-1] = np.mean(df['values'][:window])
df.loc[window-1:,'av'] = (df.loc[window-1:,'av'].fillna(df['values'])
                            .ewm(adjust=False, alpha=(window-1.)/window).mean())
  • 0
    Вы кровавый гений! Спасибо друг, это решает так много моих проблем!
  • 0
    @RPM Добро пожаловать, наконец, вы согласны с частью "Примечание"?

Ещё вопросы

Сообщество Overcoder
Наверх
Меню