2015-07-01 3 views
2

У меня есть многомерный массив в numpy (например, 4D), и я хочу указать глубину итератора numpy, и я не уверен, как это сделать, пожалуйста?Как указать глубину итератора в numpy?

Например, у меня есть массив 4D numpy, и я хочу получить элементы из итератора только для уровня 2D (так что каждый элемент будет также 2D). Есть ли способ указать такую ​​глубину в итераторе, пожалуйста?

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

Таким образом, я хотел бы этот код на выходе [1 2] s вместо 1,2 ...

x = np.array(\ 
(\ 
\ 
(\ 
(np.array([1,2]), np.array([1,2])),\ 
(np.array([1,2]), np.array([1,2]))\ 
),\ 
\ 
(\ 
(np.array([1,2]), np.array([1,2])),\ 
(np.array([1,2]), np.array([1,2]))\ 
)\ 
\ 
) 
, dtype = np.ndarray) 

for i in np.nditer(x, flags = ["refs_ok"]): 
    print i 

дает мне:

1 
2 
1 
2 
1 
2 
1 
2 
1 
2 
1 
2 
1 
2 
1 
2 

Вместо:

[1 2] 
[1 2] 
[1 2] 
[1 2] 
[1 2] 
[1 2] 
[1 2] 
[1 2] 

ответ

2

np.ndindex делает приятную работу по итерации по указанным размерам.

Ваш x представляет собой массив 4d objectdtype=ndarray становится dtype=object. Хотя с кортежами одинакового размера элементы на самом деле являются просто скалярами, а не массивами.

In [385]: x 
Out[385]: 
array([[[[1, 2], 
     [1, 2]], 

     [[1, 2], 
     [1, 2]]], 


     [[[1, 2], 
     [1, 2]], 

     [[1, 2], 
     [1, 2]]]], dtype=object) 

In [386]: x.shape 
Out[386]: (2, 2, 2, 2) 

В любом случае, np.ndindex генерирует индексы, которые будут перебирать массив заданной формы.

In [387]: for i,j in np.ndindex(x.shape[:2]): 
    print(i,j)  
    print(x[i,j]) 
    .....:  
0 0 
[[1 2] 
[1 2]] 
0 1 
[[1 2] 
[1 2]] 
1 0 
[[1 2] 
[1 2]] 
1 1 
[[1 2] 
[1 2]] 

Ключевые куски ndindex являются as_strided используются для генерации фиктивной матрицы нужного размера, и с nditermulti_index режимом для генерации индексов.

ранние примеры такого использования:

https://stackoverflow.com/a/28727290/901925

Iterating over first d axes of numpy array

Подробнее о попытке создать массив массивов (не просто выше одномерный массив чисел):

Convert a numpy array to an array of numpy arrays

Чтобы сделать x, это действительно массив массивов, вам нужно сделать что-то вроде:

In [397]: x=np.zeros((2,2,2),dtype=object) 
In [398]: for ijk in np.ndindex(x.shape): 
      x[ijk] = np.array([1,2]) 


In [399]: x 
Out[399]: 
array([[[array([1, 2]), array([1, 2])], 
     [array([1, 2]), array([1, 2])]], 

     [[array([1, 2]), array([1, 2])], 
     [array([1, 2]), array([1, 2])]]], dtype=object) 

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

for i in x.reshape(-1,2): 
    print(i) 

nditer (и расширение ndindex) описывается как эффективный, но это относится скорее к его использованию C/cython. В чистом коде Python механизм итерации не имеет значения. Действия в теле итерации обычно занимают больше времени.nditer также лучше, если вам нужна координация итерации по нескольким массивам, как в out[...] = a[...] * b[...]. Это не особенно важно, просто повторяя один массив.

http://docs.scipy.org/doc/numpy-dev/reference/arrays.nditer.html

хороший nditer учебник. Часть cython в конце - лучшая часть.

+0

Большое спасибо, я собираюсь попробовать это. Ты обалденный! Быстрое уточнение: есть ли разница в производительности между ndindex и nditer? – dval

+1

Я раскрыл вопрос эффективности. – hpaulj

+0

большое спасибо! Я новичок в numpy. Могу ли я спросить, как вы стали настолько хороши с деталями для numpy, чтобы я мог учиться у вас, пожалуйста? Есть ли хороший ресурс (книга, класс и т. Д.), Который вы бы рекомендовали? Извините, если я вас беспокою, это будет мой последний вопрос. Еще раз спасибо! :) – dval

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