2015-03-03 2 views
1

У меня есть массив, который измеряет около 2000 элементов в длину, и я хотел бы определить стандартное отклонение его по центру на каждом пикселе, сдвинув окно с некоторой относительно небольшой шириной над ним , и вычисляя StDev элементов в каждом регионе, получая массив, который является таким же количеством элементов, что и вход. Итак, если ширина была установлена ​​равной 5, StDev, центрированный на нулевом элементе, вычислял бы np.std(arr[0:3]).Статистика области массива numpy

Более конкретно, скажем, ваш входной массив был

[0.14 0.1 0.12 0.25 0.29 0.17 0.21 0.22 0.16 0.18 0.14] 

и вы хотели ширину 7. Для элемента 0, вы бы вычислить stdev([0.14 0.1 0.12 0.25]), для элемента 2, вы бы вычислить stdev([0.14 0.1 0.12 0.25 0.29]), и так на.

Похоже, наивное решение состояло в том, чтобы перебрать входной массив и либо расширить входной массив на элементы floor(width/2) (просто маскируя внешние элементы на первом и последнем нескольких пикселях), либо просто изменить используемую ширину.

Есть ли более быстрый способ сделать это, особенно тот, который не требует многократного выбора подмассивов?

ответ

2

Вы можете сделать это легко с pandas.

import pandas as pd 

data = np.random.random(20) 
stds = pd.rolling_std(data, window=7, center=True, min_periods=1) # min_periods to get the edges 
+1

Верно, но вам нужно добавить 'center = True' в аргументы, чтобы иметь то, что хотел OP. И остерегайтесь 'ddof' (степени свободы). +1 очень полезный и забыл об этом. –

+0

Хорошие уловы, спасибо @OliverW. – James

+0

Это аккуратно, но когда я пытаюсь, последние три элемента отображаются как «nan». Это также случается для кого-то еще? – DathosPachy

1

Вы можете создать очень эффективный вид памяти в массиве, используя stride_tricks, но это все равно не решит вашу проблему с окном по краям, где окно «отключено» или уменьшено. Там вы можете рассмотреть итерацию по разным размерам окон. Это даст вам ускорение скорости, если размер окна намного меньше, чем массив, по которому вы хотите вычислить стандартное отклонение (или среднее значение для этого).

import numpy as np 
from numpy.lib.stride_tricks import as_strided 

a = np.arange(20) 
windowlen = 5 
assert windowlen & 1 # this method only works for windows of uneven size 
b = np.empty(a.shape) 
b[windowlen//2:a.size - windowlen//2] = as_strided(a, 
    shape=(a.size - windowlen + 1, windowlen), 
    strides=a.strides*2).std(axis=-1) 

for ind in range(windowlen//2): # iterate over the edges where the windowsize is reduced 
    lim = windowlen//2 + 1 + ind 
    b[ind] = a[:lim].std() 
    b[-1 - ind] = a[-lim:].std() 

# b: array([ 0.81649658, 1.11803399, 1.41421356, 1.41421356, 1.41421356, 
# 1.41421356, 1.41421356, 1.41421356, 1.41421356, 1.41421356, 
# 1.41421356, 1.41421356, 1.41421356, 1.41421356, 1.41421356, 
# 1.41421356, 1.41421356, 1.41421356, 1.11803399, 0.81649658]) 

Как вы можете видеть, я добавил утверждение, потому что эта идея работает корректно, если окно имеет нечетную длину. В противном случае, где вы хотите получить std из массива, например. четыре элемента - в одном с индексом 1 или с индексом 2?

+0

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

+0

@ DathosPachy рад, что вам это нравится. Действительно, решение, предлагаемое в библиотеке pandas, очень полезно, и я бы использовал его, если бы у меня были установленные панды на машине, над которой я работаю. Если кто-то не заинтересован в установке другой библиотеки, приведенный выше код может быть прав. –

+0

Да, реквизит для использования только numpy. Я бы отказался от чистого решения, такого как панды. – James

Смежные вопросы