Коротко
sliding_window_view(a, k)возвращает все окна длиныkкак строки нового массива: изnэлементов получается(n − k + 1, k).- Это представление через strides: данные не копируются, окна пересекаются.
- Дальше — любая агрегация по последней оси:
.mean(axis=1)— скользящее среднее,.max(axis=1)— скользящий максимум. - Для многомерных данных передайте форму окна:
(2, 2)— квадратики 2 × 2. - Результат только для чтения. Чтобы окна были той же длины, что данные, сначала дополните массив через np.pad.
Синтаксис
from numpy.lib.stride_tricks import sliding_window_view
sliding_window_view(a, window_shape, axis=None)
sliding_window_view(a, 3).mean(axis=-1) # скользящее среднее
sliding_window_view(a, 3)[::2] # окна с шагом 2Параметры
ПараметрЧто делаетПо умолчанию
window_shapeразмер окна: число или кортеж по осямобязательныйaxisпо каким осям скользить; None — по всемNonewriteableразрешить запись (опасно: окна делят одни данные)FalseПримеры
from numpy.lib.stride_tricks import sliding_window_view
visits = np.array([120.0, 135, 128, 150, 162, 158, 170]) # посетители по днямsliding_window_view(visits, 3) # все окна длины 3Вывод
array([[120., 135., 128.],
[135., 128., 150.],
[128., 150., 162.],
[150., 162., 158.],
[162., 158., 170.]])sliding_window_view(visits, 3).mean(axis=1).round(2) # скользящее среднееВывод
array([127.67, 137.67, 146.67, 156.67, 163.33])
sliding_window_view(visits, 3).max(axis=1) # максимум за 3 дняВывод
array([135., 150., 162., 162., 170.])
sliding_window_view(visits, 3)[::2] # окна с шагом 2Вывод
array([[120., 135., 128.],
[128., 150., 162.],
[162., 158., 170.]])img = np.arange(16).reshape(4, 4)
patches = sliding_window_view(img, (2, 2))
print(patches.shape) # 3 × 3 окна размера 2 × 2
patches.max(axis=(-2, -1)) # максимум в каждом окнеВывод
(3, 3, 2, 2)
array([[ 5, 6, 7],
[ 9, 10, 11],
[13, 14, 15]])Подводные камни
Запись в окна запрещена
w = sliding_window_view(visits, 3)
w[0, 0] = 0 # окна пересекаются — запись запрещенаОшибка
ValueError: assignment destination is read-only
Большие окна — много вычислений
Данные не копируются, но .mean(axis=1) для окна длины k делает k сложений на каждую позицию. Для длинных окон скользящую сумму быстрее посчитать через cumsum.
c = np.cumsum(np.insert(visits, 0, 0))
((c[3:] - c[:-3]) / 3).round(2) # то же скользящее среднее за O(n)Вывод
array([127.67, 137.67, 146.67, 156.67, 163.33])
as_strided
В старом коде окна делали через np.lib.stride_tricks.as_strided. Эта функция не проверяет границы: ошибка в strides читает чужую память. Используйте sliding_window_view.