我尝试过像zip()
一样将函数np.nditer()
应用于不同维度的数组,其中迭代器应该只使用第一维度。
最小示例
a_all = np.arange(6).reshape(2,3)
idx_all = np.arange(12).reshape(2,3,2)
for a, idx in np.nditer([a_all, idx_all]):
print((a, idx))
这将引发错误:
ValueError: operands could not be broadcast together with shapes (2,3) (2,3,2)
我的使用案例
我有两个数组,其中的数据我想互相计算,而且我还有另一个数组的索引列表,所以我尝试:
a_all = np.arange(6).reshape(2,3)
b_all = np.arange(6).reshape(2,3)
idx_all = (
((0,0), (0,1), (0,2)),
((1,0), (1,1), (1,2))
)
result = np.zeros((2,3))
for a, b, idx in np.nditer([a_all, b_all, idx_all]):
result[idx] += a*b
它会抛出与最小示例相同的错误。
我假设问题在于np.nditer()
试图迭代idx_all
的所有维度,但我不知道如何将其限制在前两个维度。
我不想使用zip()
,否则我需要两个循环:
for a_, b_, idx_ in zip(a_all, b_all, idx_all):
for a, b, idx in zip(a_, b_, idx_):
result[idx] += a*b
更合理的示例
a_all = np.random.randn(2,3)
b_all = np.random.randn(2)
idx_all = (
((1,1), (2,2))
)
result = np.zeros(2)
for a, b, idx, res in np.nditer([a_all, b_all, idx_all, result], op_flags=['readwrite']):
res += a[idx] + b
1条答案
按热度按时间agxfikkp1#
看看第一个例子,修正后的数组确实一起广播(如果你不明白我做了什么改变,你已经读了足够多的基本文档)。
nditer
在“平面”意义上进行迭代,将单个元素数组(0d)传递到主体。它不像zip
那样只在第一维(或嵌套列表的外层)上进行迭代。np.vectorize
(我也不推荐它),执行相同类型的广播,但是将python标量元素传递给函数:nditer
需要和np.vectorize
一样的性能免责声明。它没有帮助,至少在python代码中使用时没有帮助。在cython
中,它可能很有用,如更大的nditer
文档页所示。此外,
nditer
输入可能很复杂,如上一个示例生成的TypeError所示。最后一个例子:
我不得不将
idx_all
更改为数组,而不是元组,这样它就可以读写了。请更仔细地阅读op_flags
文档。我们仍然会得到广播错误。它没有迭代“第一层”。