Скользящее среднее всех значений pandas DataFrame

У меня есть DataFrame pandas, и я хочу вычислить на скользящей основе среднее значение всех значений: для всех столбцов, для всех наблюдений в скользящем окне.

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

Есть лучший подход?

Настраивать

import numpy as np
import pandas as pd

np.random.seed(1)

df = pd.DataFrame(np.random.randint(0, 10, size=(10, 2)), columns=['A', 'B'])

df[df>5] = np.nan  # EDIT: add nans

Моя попытка

n_roll = 2

df_stacked = df.values
roll_avg = {}
for idx in range(n_roll, len(df_stacked)+1):
    roll_avg[idx-1] = np.nanmean(df_stacked[idx - n_roll:idx, :].flatten())

roll_avg = pd.Series(roll_avg)
roll_avg.index = df.index[n_roll-1:]
roll_avg = roll_avg.reindex(df.index)

Желаемый результат

roll_avg
Out[33]: 
0         NaN
1    5.000000
2    1.666667
3    0.333333
4    1.000000
5    3.000000
6    3.250000
7    3.250000
8    3.333333
9    4.000000

Спасибо!

с использованием прокрутки по нескольким столбцам может пригодиться. Вы можете использовать .shift или сложить, а затем перевернуть окно большего размера.
ALollz 15.08.2018 16:35
Почему в Python есть оператор "pass"?
Почему в Python есть оператор "pass"?
Оператор pass в Python - это простая концепция, которую могут быстро освоить даже новички без опыта программирования.
Некоторые методы, о которых вы не знали, что они существуют в Python
Некоторые методы, о которых вы не знали, что они существуют в Python
Python - самый известный и самый простой в изучении язык в наши дни. Имея широкий спектр применения в области машинного обучения, Data Science,...
Основы Python Часть I
Основы Python Часть I
Вы когда-нибудь задумывались, почему в программах на Python вы видите приведенный ниже код?
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
Алиса и Боб имеют неориентированный граф из n узлов и трех типов ребер:
Оптимизация кода с помощью тернарного оператора Python
Оптимизация кода с помощью тернарного оператора Python
И последнее, что мы хотели бы показать вам, прежде чем двигаться дальше, это
Советы по эффективной веб-разработке с помощью Python
Советы по эффективной веб-разработке с помощью Python
Как веб-разработчик, Python может стать мощным инструментом для создания эффективных и масштабируемых веб-приложений.
4
1
973
3
Перейти к ответу Данный вопрос помечен как решенный

Ответы 3

Чтобы получить такой же результат в случае nan, вы можете использовать column_stack на всех df.shift(i).values for i in range(n_roll), использовать nanmean на оси = 1, а затем вам нужно заменить первое значение n_roll-1 на nan после:

roll_avg = pd.Series(np.nanmean(np.column_stack([df.shift(i).values for i in range(n_roll)]),1))
roll_avg[:n_roll-1] = np.nan

и со вторым входом с nan вы получите, как и ожидалось

0         NaN
1    5.000000
2    1.666667
3    0.333333
4    1.000000
5    3.000000
6    3.250000
7    3.250000
8    3.333333
9    4.000000
dtype: float64
Ответ принят как подходящий

Вот одно решение NumPy с раздвижными окнами на view_as_windows -

from skimage.util.shape import view_as_windows

# Setup o/p array
out = np.full(len(df),np.nan)

# Get sliding windows of length n_roll along axis=0
w = view_as_windows(df.values,(n_roll,1))[...,0]

# Assign nan-ignored mean values computed along last 2 axes into o/p
out[n_roll-1:] = np.nanmean(w, (1,2))

Эффективность памяти с views -

In [62]: np.shares_memory(df,w)
Out[62]: True

Большое спасибо за ответ. Как я могу избежать использования скимейджа? похоже, не включен в стандартный дистрибутив Anaconda / моя текущая среда

FLab 15.08.2018 17:15

@FLab Вы можете использовать source code.

Divakar 15.08.2018 17:20

@FLab Или используйте strided_axis0: np.nanmean(strided_axis0(df.values, n_roll),(1,2)).

Divakar 15.08.2018 17:22

спасибо, он работает с strided_axis0. Я только что заметил, что если все значения в окне являются nan, у меня есть RuntimeWarning: среднее значение пустого фрагмента из импорта кода InteractiveConsole, и это, похоже, влияет на производительность времени, поэтому оно не так быстро, как решение `` стек '', которое я опубликовал

FLab 21.08.2018 09:55

@FLab Не уверен, как предупреждения могут повлиять на производительность. Как насчет отключения предупреждений вверху?

Divakar 21.08.2018 09:58

Используя отвечать, упомянутый в комментарии, можно сделать:

wsize = n_roll
cols = df.shape[1]
out = group.stack(dropna=False).rolling(window=wsize * cols, min_periods=1).mean().reset_index(-1, drop=True).sort_index()
out.groupby(out.index).last()
out.iloc[:nroll-1] = np.nan

В моем случае было важно указать dropna=False в stack, иначе длина скользящего окна была бы неправильной.

Но я с нетерпением жду других подходов, поскольку это не очень элегантно / эффективно.

Другие вопросы по теме