2016-11-23 3 views
1

Предположим, что у вас есть массив и вы хотите создать другой массив, значения которого равны стандартным отклонениям 10 элементов первого массива последовательно. С помощью цикла for его можно легко написать так, как показано ниже. Я хочу, чтобы избежать использования цикла для более быстрого выполнения. Какие-либо предложения?Скользящее стандартное отклонение на 1D NumPy-массиве

Code 
a = np.arange(20) 
b = np.empty(11) 
for i in range(11): 
    b[i] = np.std(a[i:i+10]) 

ответ

3

Вы можете создать 2D массив раздвижных окон с np.lib.stride_tricks.as_strided, которые были бы мнение в данных 1D массива и как таковые не будет занимать больше памяти. Затем просто использовать np.std вдоль второй оси (ось = 1) для конечного результата в векторизованном образе, как так -

W = 10 # Window size 
nrows = a.size - W + 1 
n = a.strides[0] 
a2D = np.lib.stride_tricks.as_strided(a,shape=(nrows,W),strides=(n,n)) 
out = np.std(a2D, axis=1) 

тест время выполнения

Определение функций -

def original_app(a, W): 
    b = np.empty(a.size-W+1) 
    for i in range(b.size): 
     b[i] = np.std(a[i:i+W]) 
    return b 

def vectorized_app(a, W): 
    nrows = a.size - W + 1 
    n = a.strides[0] 
    a2D = np.lib.stride_tricks.as_strided(a,shape=(nrows,W),strides=(n,n)) 
    return np.std(a2D,1) 

Сроки и проверка -

In [460]: # Inputs 
    ...: a = np.arange(10000) 
    ...: W = 10 
    ...: 

In [461]: np.allclose(original_app(a, W), vectorized_app(a, W)) 
Out[461]: True 

In [462]: %timeit original_app(a, W) 
1 loops, best of 3: 522 ms per loop 

In [463]: %timeit vectorized_app(a, W) 
1000 loops, best of 3: 1.33 ms per loop 

Итак, около 400x ускорение там!

+0

Это немного сложнее, но быстрее решение. Спасибо! –

+0

принял ваше решение. это работает –

0

Не так фантазии, но код, без петель было бы что-то вроде этого:

a = np.arange(20) 
b = [a[i:i+10].std() for i in range(len(a)-10)] 
Смежные вопросы