如何以列表方式迭代 numpy 数组(元组)

问题描述 投票:0回答:2

在迭代 numpy 元组数组时出现错误

TypeError: Iterator operand or requested dtype holds references, but the REFS_OK flag was not enabled
如下:

import numpy as np

tmp = np.empty((), dtype=object)
tmp[()] = (0, 0)
arr = np.full(10, tmp, dtype=object)

for a, b in np.nditer(arr):
    print(a, b)

如何解决这个问题?

python python-3.x numpy iterable-unpacking
2个回答
0
投票

错误消息实际上告诉您问题和解决方法:您正在尝试迭代引用类型数组(即对象,

dtype=object
),但您没有启用
np.nditer
来迭代引用类型.

要解决此问题,请在调用

np.nditer
时设置 REFS_OK 标志:

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

请注意,您的代码中还有第二个问题。进行此修复后,

np.nditer
将生成一个零维数组的引用,该数组不能解压缩到
a, b
中(即使该零维数组包含一个 2 元组)。相反,您可以使用
.item()
提取元组并将其解压缩到循环体中:

for x in np.nditer(arr, flags=["refs_ok"]):
    a, b = x.item()

0
投票
In [71]: tmp = np.empty((), dtype=object)
    ...: tmp[()] = (0, 0)
    ...: arr = np.full(10, tmp, dtype=object)

你不需要

nditer
遍历这个数组:

In [74]: for i in arr:print(i)
(0, 0)
(0, 0)
(0, 0)
...
(0, 0)

nditer
只会让生活变得更复杂,而且不会更快,特别是对于像
print
这样的事情。谁或什么推荐
nditer

就此而言,您可以简单地打印数组:

In [75]: arr
Out[75]: 
array([(0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0),
       (0, 0), (0, 0)], dtype=object)

但是让我们看看别的东西——这个对象 dtype 数组的元素的

id

In [76]: [id(i) for i in arr]
Out[76]: 
[1562261311040,
 1562261311040,
 ...
 1562261311040,
 1562261311040]

你创建了一个数组,其中包含 10 个对同一个元组的引用。那是你想要的吗?是

full
做到了。

为了在每个槽中制作不同的元组,我打算建议这个列表理解,但后来意识到它只是产生了一个二维数组:

In [83]: arr1 = np.array([(0,0) for _ in range(5)]); arr1
Out[83]: 
array([[0, 0],
       [0, 0],
       [0, 0],
       [0, 0],
       [0, 0]])

要用实际的元组(不同的)创建一个对象 dtype 数组,我们必须做类似的事情:

In [84]: arr1 = np.empty(5, object); arr1
Out[84]: array([None, None, None, None, None], dtype=object)    
In [85]: arr1[:] = [(0,i) for i in range(5)]    
In [86]: arr1
Out[86]: array([(0, 0), (0, 1), (0, 2), (0, 3), (0, 4)], dtype=object)

但这让我们回到了基本问题——为什么首先要创建一个元组数组?重点是什么。

numpy
最适用于多维数值数组。在许多方面,对象 dtype 数组只是美化(或贬低)列表。

© www.soinside.com 2019 - 2024. All rights reserved.