简体   繁体   English

NumPy多维数组迭代如何工作? (有和没有nditer)

[英]How does NumPy multidimensional array iteration work? (With and without nditer)

Note: I am not sure if this is a duplicate or not -- please let me know if it is (and close the question). 注意:我不确定这是否重复 - 如果是,请告诉我(并关闭问题)。

If one has a 1-dimensional NumPy array vector , then if one writes a for loop of the form: 如果有一个具有1维NumPy数组vector ,那么如果有人写一个for循环的形式:

for element in vector :
    print(element)

The result will print each element of the NumPy array. 结果将打印NumPy数组的每个元素。

If one has a 2-dimensional NumPy array matrix , then if one writes a for loop of the form: 如果有一个二维NumPy数组matrix ,那么如果有人写一个for循环的形式:

for vector in matrix :
    print(vector)

The result will print each row of the 2-dimensional NumPy array, ie it will print 1-dimensional NumPy arrays, and it will not print each element of the array individually. 结果将打印2维NumPy数组的每一行,即它将打印1维NumPy数组,并且它不会单独打印数组的每个元素。

However, if one instead writes the for loop as: 但是,如果有人将for循环写为:

import numpy
for element in numpy.nditer(matrix) :
     print(element)

The result will print each element of the 2-dimensional NumPy array. 结果打印二维NumPy数组的每个元素。

Question: What happens if one has a 3-dimensional NumPy array, tensor ? 问题:如果有一个三维NumPy数组, tensor会怎么样?

a. 一个。 If one writes a for loop of the form: 如果写一个for循环的形式:

for unknownType in tensor :
     print(unknownType)

Will this print the constituent 2-dimensional NumPy (sub-)arrays of tensor ? 这会打印构成二维NumPy(子) tensor阵列吗?

Ie for an n-dimensional NumPy array nArray , does for unknownType in nArray : iterate over the constituent (n-1)-dimensional NumPy (sub-)arrays of nArray ? 即,对于n维阵列NumPy的nArray ,确实for unknownType in nArray :遍历组成第(n-1)维NumPy的(子)的阵列nArray

b. If one writes a for loop of the form: 如果写一个for循环的形式:

for unknownType in numpy.nditer(tensor) :
    print(unknownType)

Will this print the elements of tensor ? 这会打印出tensor元素吗? Or will it print the constituent 1-dimensional NumPy (sub-)arrays of the constituent 2-dimensional NumPy (sub-)arrays of tensor ? 或者它会打印成分二维NumPy(子)阵列tensor的组成1维NumPy(子)数组吗?

Ie for an n-dimensional NumPy array nArray , does for unknownType in nditer(nArray) : iterate over the elements of nArray ? 即n维NumPy数组nArrayfor unknownType in nditer(nArray) :迭代nArray的元素? Or does it iterate over the constituent (n-2)-dimensional NumPy (sub-)arrays of the constituent (n-1)-dimensional NumPy (sub-)arrays of nArray ? 或者它是否在nArray的成分(n-1)维NumPy(子)数组的成分(n-2)维NumPy(子)数组上进行nArray

It is unclear to me from the name nditer , since I don't know what "nd" stands for ("iter" is obviously short for "iteration"). 从名字nditer我不清楚,因为我不知道“nd”代表什么(“iter”显然是“迭代”的缩写)。 And presumably one can think of the elements as "0-dimensional NumPy arrays", so the examples given to me for 2-dimensional NumPy arrays are ambiguous. 并且可能人们可以将这些元素视为“0维NumPy数组”,因此给我的二维NumPy数组的示例是模糊的。

I've looked at the np.nditer documentation but honestly I didn't understand the examples or what they were trying to demonstrate -- it seems like it was written for programmers (which I am not) by programmers. 我查看了np.nditer文档,但说实话,我不明白这些示例或者他们试图演示的内容 - 它似乎是程序员为程序员编写的(我不是)。

a) 一个)

for x in arr: iterates on the 1st dimension of an array. for x in arr:迭代数组的第一维。

In [233]: for x in np.arange(24).reshape((2,3,4)):
     ...:     print(x.shape)
     ...:     
(3, 4)
(3, 4)

I think of it as for x in list(arr):... . 我认为它是for x in list(arr):... It breaks the array into a list of subarrays. 它将数组分成一个子数组列表。

b) b)

It's tricky to control the depth of iteration with nditer . nditer控制迭代深度很棘手。 As a default it iterates at the element level. 默认情况下,它会在元素级别进行迭代。 The tutorial page shows some tricks using buffers and order. 教程页面显示了使用缓冲区和顺序的一些技巧。 but the best way I seen is to use ndindex . 但我看到的最好的方法是使用ndindex

ndindex constructs a dummy array of the right size, and does multi_index iteration. ndindex构造一个正确大小的虚拟数组,并执行multi_index迭代。

For example to iterate on the 1st 2 dimensions of a 3d array: 例如,迭代3d数组的前2个维度:

In [237]: arr = np.arange(24).reshape(2,3,4)
In [240]: for idx in np.ndindex(arr.shape[:2]):
     ...:     print(idx, arr[idx], arr[idx].sum())
     ...:      
(0, 0) [0 1 2 3] 6
(0, 1) [4 5 6 7] 22
(0, 2) [ 8  9 10 11] 38
(1, 0) [12 13 14 15] 54
(1, 1) [16 17 18 19] 70
(1, 2) [20 21 22 23] 86

I could do the same iteration with 我可以用同样的迭代

for i in range(2):
    for j in range(3):
         arr[i,j]...

or 要么

arr1 = arr.reshape(-1,4)
for ij in range(6):
    arr1[ij]....

Speed will be basically the same - all poor compared to array functions that work on the whole 3d array at once, or ones that take some sort of axis parameter. 速度基本相同 - 与同时在整个3d数组上工作的数组函数相比,或者采用某种axis参数的数据都比较差。

In [241]: arr.sum(axis=2)
Out[241]: 
array([[ 6, 22, 38],
       [54, 70, 86]])

The class for numpy as arrays is np.ndarray . numpy作为数组的类是np.ndarray Presumably nditer is named like that. 据推测, nditer就是这样命名的。 nditer was written as a way of consolidating the various that c level code could iterate on arrays, especially several broadcastable ones. nditer是作为一种整合各种c级代码可以在数组上迭代的方式编写的,特别是几个可广播的代码。 The np.nditer function gives access to the c level iterator. np.nditer函数可以访问c级迭代器。 But since the actually iteration is still being done in Python code, so there's little to no speed advantage. 但是由于实际迭代仍然在Python代码中完成,所以几乎没有速度优势。

If you just use a for loop the iteration is over the first dimension, if the array has only one dimension this will be the elements, if it's 2D it will be the rows, if it's 3D it will iterate over the planes, ... 如果你只是使用for循环,那么迭代就在第一个维度上,如果数组只有一个维度,那么这将是元素,如果它是2D,它将是行,如果它是3D,它将迭代飞机,...

However nditer is a ND (stands for n-dimensional) iterator. 然而, nditer是ND(代表n维)迭代器。 It will iterate over each element in the array. 它将迭代数组中的每个元素。 It's (roughly!) equivalent to for item in your_array.ravel() (iterating over a flattened "view" of the array). 它(大致!)等同for item in your_array.ravel() (迭代数组的展平“视图”)。 For 1D arrays it iterates over the elements, for 2D arrays it iterates first over the elements in the first row, then over the second row, and so on. 对于1D数组,它迭代元素,对于2D数组,它首先迭代第一行中的元素,然后遍历第二行,依此类推。

Note that nditer is much more powerful than that, it can iterate over multiple arrays at once, you can buffer the iteration and a lot of other stuff. 请注意, nditer比它强大得多,它可以一次迭代多个数组,你可以缓冲迭代和许多其他东西。


However with NumPy you generally don't want to use a for -loop or np.nditer . 但是对于NumPy,您通常希望使用for -loop或np.nditer There are lots of "vectorized" operations that make manual iteration (in most cases) unnecessary. 许多 “向量化”操作使得手动迭代(在大多数情况下)不必要。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM