Скользящее среднее по обратной диагонали в Python - PullRequest
0 голосов
/ 25 февраля 2019

У меня есть сводная таблица панд, которая ранее была смещена и теперь выглядит следующим образом:

pivot
    A    B    C    D    E
0  5.3  5.1  3.5  4.2  4.5
1  5.3  4.1  3.5  4.2  NaN
2  4.3  4.1  3.5  NaN  NaN
3  4.3  4.1  NaN  NaN  NaN
4  4.3  NaN  NaN  NaN  NaN

Я пытаюсь вычислить скользящее среднее с переменным окном (в данном случае 3 и 4 периода)по обратной диагонали итерируя по каждому столбцу и пытаясь сохранить это значение в новом кадре данных, который будет выглядеть следующим образом:

expected_df with a 3 periods window
    A    B    C    D    E
0  4.3  4.1  3.5  4.2  4.5

expected_df with a 4 periods window
    A    B    C    D    E
0  4.5  4.3  3.5  4.2  4.5

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

subset
    A    B    C    D    E
0  4.3  4.1  3.5  4.2  4.5
1  4.3  4.1  3.5  4.2  NaN
2  4.3  4.1  3.5  NaN  NaN

Для этого я попытался построить следующее для цикла:

df2 = pd.DataFrame()
size = pivot.shape[0]
window = 3

for i in range(size): 
    df2[i] = pivot.iloc[size-window-i:size-i,i]

Что не работает, даже когда этот pivot.iloc[size-window-i:size-i,i] возвращает нужные мне значения, когда я вручную передаю индексы, но в цикле for он пропускает первое значение второго столбца и так далее:

df2
    A    B    C    D    E
0  4.3  NaN  NaN  NaN  NaN
1  4.3  4.1  NaN  NaN  NaN
2  4.3  4.1  3.5  NaN  NaN

Кто-нибудь имеет хорошее представление о том, как рассчитать скользящее среднее или как исправить часть цикла for?Заранее спасибо за ваши комментарии.

1 Ответ

0 голосов
/ 25 февраля 2019

IIUC:

shift все назад

shifted = pd.concat([df.iloc[:, i].shift(i) for i in range(df.shape[1])], axis=1)
shifted

     A    B    C    D    E
0  5.3  NaN  NaN  NaN  NaN
1  5.3  5.1  NaN  NaN  NaN
2  4.3  4.1  3.5  NaN  NaN
3  4.3  4.1  3.5  4.2  NaN
4  4.3  4.1  3.5  4.2  4.5

Тогда вы можете получить свое среднее значение.

# Change this ? to get the last n number of rows
shifted.iloc[-3:].mean()

A    4.3
B    4.1
C    3.5
D    4.2
E    4.5
dtype: float64

Или скользящее среднее

#   Change this ? to get the last n number of rows
shifted.rolling(3, min_periods=1).mean()

          A         B    C    D    E
0  5.300000       NaN  NaN  NaN  NaN
1  5.300000  5.100000  NaN  NaN  NaN
2  4.966667  4.600000  3.5  NaN  NaN
3  4.633333  4.433333  3.5  4.2  NaN
4  4.300000  4.100000  3.5  4.2  4.5

Скольжение шагов

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

Кроме того, я бы не стал этим пользоваться.Я просто хотел понять, как захватывать диагональные элементы с помощью шагов.Для меня это было больше практикой, и я хотел поделиться.

from numpy.lib.stride_tricks import as_strided as strided

a = df.values

roll = 3
r_ = roll - 1  # one less than roll

h, w = a.shape
w_ = w - 1  # one less than width

b = np.empty((h + 2 * w_ + r_, w), dtype=a.dtype)
b.fill(np.nan)
b[w_ + r_:-w_] = a

s0, s1 = b.strides
a_ = np.nanmean(strided(b, (h + w_, roll, w), (s0, s0, s1 - s0))[w_:], axis=1)

pd.DataFrame(a_, df.index, df.columns)

          A         B    C    D    E
0  5.300000       NaN  NaN  NaN  NaN
1  5.300000  5.100000  NaN  NaN  NaN
2  4.966667  4.600000  3.5  NaN  NaN
3  4.633333  4.433333  3.5  4.2  NaN
4  4.300000  4.100000  3.5  4.2  4.5

Нумба

Я чувствую себя лучше, чем когда я использую шаги

import numpy as np
from numba import njit
import warnings

@njit
def dshift(a, roll):
  h, w = a.shape
  b = np.empty((h, roll, w), dtype=np.float64)
  b.fill(np.nan)

  for r in range(roll):
    for i in range(h):
      for j in range(w):
        k = i - j - r
        if k >= 0:
          b[i, r, j] = a[k, j]

  return b

with warnings.catch_warnings():
  warnings.simplefilter('ignore', category=RuntimeWarning)

  df_ = pd.DataFrame(np.nanmean(dshift(a, 3), axis=1, ), df.index, df.columns)

df_

          A         B    C    D    E
0  5.300000       NaN  NaN  NaN  NaN
1  5.300000  5.100000  NaN  NaN  NaN
2  4.966667  4.600000  3.5  NaN  NaN
3  4.633333  4.433333  3.5  4.2  NaN
4  4.300000  4.100000  3.5  4.2  4.5
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...