【问题标题】:numpy 2d and 1d addition flatnumpy 2d 和 1d 加法平面
【发布时间】:2016-02-15 02:03:04
【问题描述】:

在开始使用 NumPy 时使用 NumPy Book 中的示例时,我注意到了一个示例:

a = zeros((4, 5))
b = ones(6)
add(b, b, a[1:3, 0:3].flat)
print(a)

返回

array([[0, 0, 0, 0, 0]
       [2, 2, 2, 0, 0]
       [2, 2, 2, 0, 0]
       [0, 0, 0, 0, 0]])

但是,当我尝试此代码时,会导致以下错误:

add(b, b, a[1:3, 0:3].flat)

TypeError: 返回数组必须是 ArrayType"

谁能解释一下这个问题?

【问题讨论】:

    标签: python arrays numpy


    【解决方案1】:

    如果 numpy.add 有 2 个参数,它们将被视为 added 的两个操作数。如果您提供 3 个参数,则前两个是添加的参数,第三个是 result。实际上不是结果,而是应该保存结果的数组。

    所以您添加了bb,并希望将其存储在a[1:3, 0:3].flat 中。

    让我们尝试np.add(b, b),它给出了

    import numpy as np
    a = np.zeros((4, 5))
    b = np.ones(6)
    np.add(b, b)
    # returns array([ 2.,  2.,  2.,  2.,  2.,  2.])
    

    所以现在我尝试了a[1:3, 0:3].flat,它返回<numpy.flatiter at 0x22204e80c10>。这意味着它返回一个iterator,所以它不是数组。但是我们不需要迭代器,我们需要一个数组。有一种方法叫做ravel()。所以尝试a[1:3, 0:3].ravel() 返回:

    array([ 0.,  0.,  0.,  0.,  0.,  0.])
    

    所以我们有一个数组。特别是数组也可用于存储结果(相同的形状!)。所以我尝试了:

    np.add(b, b, a[1:3, 0:3].ravel())
    # array([ 2.,  2.,  2.,  2.,  2.,  2.])
    

    但是让我们看看a是否发生了变化:

    a
    #array([[ 0.,  0.,  0.,  0.,  0.],
    #       [ 0.,  0.,  0.,  0.,  0.],
    #       [ 0.,  0.,  0.,  0.,  0.],
    #       [ 0.,  0.,  0.,  0.,  0.]])
    

    所以a 没有改变。那是因为ravel() 仅在可能的情况下返回一个视图(赋值将传播到解开的数组),否则它返回一个副本。并且将结果保存在副本中是毫无意义的,因为out 参数的全部意义在于操作是就地完成的。我只是猜测为什么要复制,但我认为这是因为我们从更大的数组中取出了一部分,而该部分在内存中并不连续。

    所以我建议你在这种情况下不要使用out参数,而是使用np.add的返回并将其存储在a的指定区域内:

    a[1:3, 0:3] = np.add(b, b).reshape(2,3) # You need to reshape here!
    a
    #array([[ 0.,  0.,  0.,  0.,  0.],
    #       [ 2.,  2.,  2.,  0.,  0.],
    #       [ 2.,  2.,  2.,  0.,  0.],
    #       [ 0.,  0.,  0.,  0.,  0.]])
    

    a[1:3, 0:3].flat = np.add(b, b) 也有效。

    我认为这本书要么已经过时,并且可以与较旧的numpy 版本一起使用,要么根本无法使用,这是书中的一个错误。

    【讨论】:

    • Python 版本 - 3.5,NumPy - 1.10.4。我所指的书是 Travis E. Oliphant 的 NumPy 指南,2006 年。这可能也是因为 Python 版本的冲突。不管怎样,谢谢你这么详细的回答。很有帮助!
    • 感谢您的反馈,这正是我正在使用的版本,我确信这是 numpy 的错误(或 2006 年至今已弃用的东西),因为 a[1:3, 0:3].flat = np.add(b, b) 也有效。这应该等同于您的np.add(b, b, a[1:3, 0:3].flat)
    • a[...].flat=np.add(b,b) 有效。 flat doc 显示了此分配的使用。显然,有些东西改变了以禁用它作为 ufunc out 参数。
    • 是的,我也注意到了这一点,并将其包含在答案中。我还在 numpy 上提出了一个问题:github.com/numpy/numpy/issues/7244。也许他们知道为什么它不起作用。
    • 感谢@MSeifert。虽然通过分配 np.add(b, b) 来替换数组值是可行的,但它只替换数组内的值,但实际上并没有添加其中的值。可以将值引用到另一个数组“k = a[1:3, 0:3].flat; a[1:3, 0:3].flat = add(b*2, k)”,但它如果模块可以“固定”就好了。
    猜你喜欢
    • 2017-06-18
    • 2021-01-28
    • 1970-01-01
    • 2020-10-24
    • 1970-01-01
    • 2021-10-12
    • 1970-01-01
    • 1970-01-01
    • 2022-01-17
    相关资源
    最近更新 更多