2015-10-28 3 views
3

Каков самый быстрый способ перебора всех элементов в массиве 3D NumPy? Если array.shape = (r,c,z), должно быть что-то быстрее, чем это:Итерация по многомерному массиву Numpy

x = np.asarray(range(12)).reshape((1,4,3)) 

#function that sums nearest neighbor values 
x = np.asarray(range(12)).reshape((1, 4,3)) 

#e is my element location, d is the distance 
def nn(arr, e, d=1): 
    d = e[0] 
    r = e[1] 
    c = e[2] 
    return sum(arr[d,r-1,c-1:c+2]) + sum(arr[d,r+1, c-1:c+2]) + sum(arr[d,r,c-1]) + sum(arr[d,r,c+1]) 

Вместо создания вложенной for петлю, как показано ниже, чтобы создать свои ценности из e, чтобы запустить функцию nn для каждого пикселя:

for dim in range(z): 
    for row in range(r): 
     for col in range(c): 
      e = (dim, row, col) 

Я хотел бы оцифровать мою функцию nn таким образом, чтобы извлекать информацию о местоположении для каждого элемента (например, e = (0,1,1)) и итерации по всем элементам в моей матрице без необходимости вручную вводить каждое локальное значение e ИЛИ создание беспорядочного вложенного цикла. Я не уверен, как применить np.vectorize к этой проблеме. Благодаря!

+0

Не должно быть 'array [dim, row, col] = someValue' вместо этого? Вы присваиваете одинаковое значение 'someValue' всем его элементам? Подумайте о том, как вводить образец ввода, чтобы узнать, что вы имеете в виду? – Divakar

+3

Кроме того, в NumPy самый быстрый способ - * не * итерировать вообще, но выполнять операции векторизованным образом. Можете ли вы это сделать или нет, будет зависеть от самой предполагаемой операции, которую вы хотели бы выполнять в каждой итерации. – Divakar

+0

Спасибо за изменения! Теперь, для * правильной * векторизации и, следовательно, заметного ускорения, фактическая реализация 'nn' должна быть известна. В общем случае можно было бы изучить ['numpy.vectorize'] (http://docs.scipy.org/doc/numpy/reference/generated/numpy.vectorize.html). – Divakar

ответ

0

Легко векторизации по d размерности:

def nn(arr, e): 
     r,c = e # (e[0],e[1]) 
     return np.sum(arr[:,r-1,c-1:c+2],axis=2) + np.sum(arr[:,r+1,c-1:c+2],axis=2) + 
      np.sum(arr[:,r,c-1],axis=?) + np.sum(arr[:,r,c+1],axis=?) 

теперь только перебирать строки и Col размеров, возвращая вектор, который присваивается соответствующий слот в x.

for row in <correct range>: 
    for col in <correct range>: 
     x[:,row,col] = nn(data, (row,col)) 

Следующий шаг, чтобы сделать

строк = [:, None] COLS = обр [:, строки-1, смещ_по_столбцам + 2] + обр [:, строки COLS + 2 ] и т.д.

Такого рода проблемы пришло много раз, с различными описаниями - свертка, сглаживающие, фильтрация и т.д.

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

Converting a nested loop calculation to Numpy for speedup

вопрос похож на ваш. Там только два уровня цикла, и выражение сумма отличается, но я думаю, что он имеет те же вопросы:

for h in xrange(1, height-1): 
    for w in xrange(1, width-1): 
     new_gr[h][w] = gr[h][w] + gr[h][w-1] + gr[h-1][w] + 
       t * gr[h+1][w-1]-2 * (gr[h][w-1] + t * gr[h-1][w]) 
0

Вот что я в конечном итоге делает. Поскольку я возвращаю вектор xv и вставляя его в большой 3D-массив lag, это должно ускорить процесс, не так ли? data - мой входной набор данных.

def nn3d(arr, e): 
    r,c = e 

    n = np.copy(arr[:,r-1:r+2,c-1:c+2]) 
    n[:,1,1] = 0 

    n3d = np.ma.masked_where(n == nodata, n) 

    xv = np.zeros(arr.shape[0]) 
    for d in range(arr.shape[0]): 
     if np.ma.count(n3d[d,:,:]) < 2: 
      element = nodata 
     else: 
      element = np.sum(n3d[d,:,:])/(np.ma.count(n3d[d,:,:])-1) 
     xv[d] = element 

    return xv 

lag = np.zeros(shape = data.shape)   
for r in range(1,data.shape[1]-1): #boundary effects 
    for c in range(1,data.shape[2]-1): 
     lag[:,r,c] = nn3d(data,(r,c)) 
Смежные вопросы