NumPy多维数组迭代是如何工作的?(有无nditer)

2024-09-27 21:29:49 发布

您现在位置:Python中文网/ 问答频道 /正文

注:我不确定这是否是重复的——请告诉我是否是重复的(并结束问题)。

如果有一个一维NumPy数组vector,那么如果编写一个for循环,格式如下:

for element in vector :
    print(element)

结果将打印NumPy数组的每个元素。

如果有一个二维NumPy数组matrix,那么如果编写一个for循环的形式:

for vector in matrix :
    print(vector)

结果将打印二维NumPy数组的每一行,即打印一维NumPy数组,并且将而不是分别打印数组的每个元素。

但是,如果改为将for循环写入:

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

结果打印二维NumPy数组的每个元素。

问题:如果有一个三维NumPy数组,tensor会发生什么?

a.如果要编写窗体的for循环:

for unknownType in tensor :
     print(unknownType)

这是否会打印构成tensor的二维NumPy(sub-)数组?

即,对于n维NumPy数组nArray,是否for unknownType in nArray :nArray的组成(n-1)维NumPy(子)数组上迭代?

b.如果一个人写了表单的for循环:

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

这会打印tensor的元素吗?或者它会打印组成二维NumPy(子)数组的一维NumPy(子)数组吗?

即,对于n维NumPy数组nArray,是否for unknownType in nditer(nArray) :迭代nArray的元素?或者它是否迭代组成(n-2)维NumPy(sub-)数组的组成(n-1)维NumPy(sub-)数组的nArray

从名称nditer我不清楚,因为我不知道“nd”代表什么(“iter”显然是“iter”的缩写)。而且人们可能认为元素是“0维NumPy数组”,所以给我的2维NumPy数组的例子是模棱两可的。

我已经看过^{} documentation了,但老实说,我不理解这些例子,也不理解它们试图演示的内容——它似乎是由程序员(我不是)为程序员编写的。


Tags: innumpy元素for数组elementmatrixtensor
2条回答

如果只使用for循环,则迭代在第一个维度上,如果数组只有一个维度,则这将是元素,如果是2D,则是行,如果是3D,则将在平面上迭代。。。

然而nditer是一个ND(代表n维)迭代器。它将遍历数组中的每个元素。大概是吧相当于for item in your_array.ravel()(在数组的平坦“视图”上迭代)。对于一维数组,它在元素上迭代;对于二维数组,它首先在第一行中的元素上迭代,然后在第二行上迭代,依此类推。

注意nditer比它强大得多,它可以一次在多个数组上迭代,您可以缓冲迭代和许多其他东西。


但是对于NumPy,您通常不想使用for-循环或np.nditer。有许多“矢量化”操作使得手动迭代(在大多数情况下)不必要。

(一)

for x in arr:迭代数组的第一个维度。

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

我认为它是for x in list(arr):...。它将数组分解成一个子数组列表。

(二)

nditer控制迭代的深度是很棘手的。默认情况下,它在元素级别迭代。教程页面显示了一些使用缓冲区和顺序的技巧。但我看到的最好的方法是使用ndindex

ndindex构造一个大小合适的伪数组,并执行multi_index迭代。

例如,要在三维数组的前二维上迭代:

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

我可以做同样的迭代

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

或者

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

速度基本上是一样的——与同时处理整个3d数组的数组函数或采用某种axis参数的数组函数相比,这一切都很糟糕。

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

numpy as数组的类是np.ndarray。大概nditer就是这样命名的。nditer是作为一种整合c级代码可以在数组上迭代的各种方法而编写的,特别是一些可广播的数组。np.nditer函数允许访问c级迭代器。但由于实际的迭代仍在Python代码中完成,因此几乎没有速度优势。

相关问题 更多 >

    热门问题