【问题标题】:Unsuccessful append to an empty NumPy array未成功追加到空 NumPy 数组
【发布时间】:2013-11-07 22:18:30
【问题描述】:

我正在尝试使用 append 用值填充一个空(不是 np.empty!)数组,但我遇到了错误:

我的代码如下:

import numpy as np
result=np.asarray([np.asarray([]),np.asarray([])])
result[0]=np.append([result[0]],[1,2])

我得到:

ValueError: could not broadcast input array from shape (2) into shape (0)

【问题讨论】:

    标签: python arrays numpy append


    【解决方案1】:

    numpy.append 总是在添加新值之前复制数组。您的代码相当于以下内容:

    import numpy as np
    result = np.zeros((2,0))
    new_result = np.append([result[0]],[1,2])
    result[0] = new_result # ERROR: has shape (2,0), new_result has shape (2,)
    

    也许你的意思是这样做?

    import numpy as np
    result = np.zeros((2,0))
    result = np.append([result[0]],[1,2])
    

    【讨论】:

    • 实际上结果的元素为零...但是您建议的观点完全不同!
    • np.append 只是一个concatenatereturn concatenate((arr, values), axis=axis)
    【解决方案2】:

    numpy.append 与 python 中的 list.append 完全不同。我知道这让一些刚接触 numpy 的程序员望而却步。 numpy.append 更像是连接,它创建一个新数组并用旧数组中的值和要附加的新值填充它。例如:

    import numpy
    
    old = numpy.array([1, 2, 3, 4])
    new = numpy.append(old, 5)
    print old
    # [1, 2, 3, 4]
    print new
    # [1, 2, 3, 4, 5]
    new = numpy.append(new, [6, 7])
    print new
    # [1, 2, 3, 4, 5, 6, 7]
    

    我认为您可以通过以下方式实现您的目标:

    result = numpy.zeros((10,))
    result[0:2] = [1, 2]
    
    # Or
    result = numpy.zeros((10, 2))
    result[0, :] = [1, 2]
    

    更新:

    如果您需要使用循环创建一个 numpy 数组,并且您不提前知道数组的最终大小,您可以执行以下操作:

    import numpy as np
    
    a = np.array([0., 1.])
    b = np.array([2., 3.])
    
    temp = []
    while True:
        rnd = random.randint(0, 100)
        if rnd > 50:
            temp.append(a)
        else:
            temp.append(b)
        if rnd == 0:
             break
    
     result = np.array(temp)
    

    在我的示例中,结果将是一个 (N, 2) 数组,其中 N 是循环运行的次数,但显然您可以根据需要对其进行调整。

    新的更新

    您看到的错误与类型无关,它与您尝试连接的 numpy 数组的形状有关。如果你做np.append(a, b)ab的形状需要匹配。如果你附加一个 (2, n) 和 (n,) 你会得到一个 (3, n) 数组。您的代码正在尝试将 (1, 0) 附加到 (2,)。这些形状不匹配,因此您会收到错误消息。

    【讨论】:

    • 这对我没有帮助。因为我想动态地将数字附加到我的数组中!
    • 我不确定您所说的“动态”是什么意思,也许您正在寻找dynamic array?我在任何语言中使用过的动态数组的最佳实现是@987654322 @. 不幸的是 numpy 数组不是动态数组,但你可以通过复制来追加它们。
    • 是的,这正是我的意思。但是,正如我在上面的评论中已经说过的那样,我可以理解的 Python 的这个错误并没有多大意义,因为它是免费的!不过谢谢!那我就用列表吧。
    • @Naji Python 不是无类型的;它是动态类型的。许多(大多数?)动态语言都有一些不可变的数据结构,或者限制了你可以用它们做什么。
    【解决方案3】:

    此错误是由于您试图将形状 (0,) 的对象定义为形状 (2,) 的对象。如果您附加您想要的内容而不强制它等于 result[0] 则没有任何问题:

    b = np.append([result[0]], [1,2])
    

    但是当您定义 result[0] = b 时,您会将不同形状的对象等同起来,您不能这样做。你想做什么?

    【讨论】:

    • 这是有道理的,尽管考虑到 python 是无类型的,这看起来很蹩脚,以至于在分配变量后无法更改变量的类型!
    • 我不知道你到底想做什么,但我认为你可能想使用列表而不是 numpy 数组。列表更灵活。
    • 我要做的是创建一个空的二维数组,并用我得到的属于 index=0 或 index=1 的值动态填充它。
    • @Naji 您可以在分配 变量 后更改它的类型,只需将其分配给不同的值即可。在创建 后,您通常无法更改它的类型。特别是对于 numpy 数组,出于性能原因,使用 C 实现的数据结构会带来额外的麻烦。
    • np.arrays 最好被认为是固定大小的容器。虽然它们可以从 Python 列表构建,但它们并不是为增长而设计的。
    【解决方案4】:

    这是在 Ipython 中运行代码的结果。注意result 是一个(2,0) 数组,2 行,0 列,0 个元素。 append 产生一个 (2,) 数组。 result[0](0,) 数组。您的错误消息与尝试将该 2 项数组分配到大小为 0 的插槽有关。由于resultdtype=float64,因此只能将标量分配给其元素。

    In [65]: result=np.asarray([np.asarray([]),np.asarray([])])
    
    In [66]: result
    Out[66]: array([], shape=(2, 0), dtype=float64)
    
    In [67]: result[0]
    Out[67]: array([], dtype=float64)
    
    In [68]: np.append(result[0],[1,2])
    Out[68]: array([ 1.,  2.])
    

    np.array 不是 Python 列表。数组的所有元素都是同一类型(由dtype 指定)。另请注意,result 不是数组数组。

    结果也可以构建为

    ll = [[],[]]
    result = np.array(ll)
    

    同时

    ll[0] = [1,2]
    # ll = [[1,2],[]]
    

    结果不一样。

    np.zeros((2,0)) 也会生成您的result

    其实result还有一个怪癖。

    result[0] = 1
    

    不会更改result 的值。它接受分配,但由于它有 0 列,所以没有地方放置 1。此分配将在结果创建为np.zeros((2,1)) 时起作用。但这仍然不能接受列表。

    但如果result 有 2 列,那么您可以将 2 元素列表分配给其中的一行。

    result = np.zeros((2,2))
    result[0] # == [0,0]
    result[0] = [1,2]
    

    您究竟希望resultappend 操作后是什么样子?

    【讨论】:

    • 投票。但是我认为您已经写的内容已包含在其他答案中。还是谢谢
    【解决方案5】:

    SO 线程 'Multiply two arrays element wise, where one of the arrays has arrays as elements' 有一个从数组构造数组的示例。如果子数组的大小相同,numpy 会创建一个二维数组。但如果它们的长度不同,它会用dtype=object 组成一个数组,并且子数组保持它们的身份。

    之后,您可以执行以下操作:

    In [5]: result=np.array([np.zeros((1)),np.zeros((2))])
    
    In [6]: result
    Out[6]: array([array([ 0.]), array([ 0.,  0.])], dtype=object)
    
    In [7]: np.append([result[0]],[1,2])
    Out[7]: array([ 0.,  1.,  2.])
    
    In [8]: result[0]
    Out[8]: array([ 0.])
    
    In [9]: result[0]=np.append([result[0]],[1,2])
    
    In [10]: result
    Out[10]: array([array([ 0.,  1.,  2.]), array([ 0.,  0.])], dtype=object)
    

    但是,我并没有立即看出这比一个或多个纯 Python 列表有什么优势。它不像二维数组那样工作。例如我必须使用result[0][1],而不是result[0,1]。如果子数组的长度都相同,我必须使用np.array(result.tolist()) 来生成二维数组。

    【讨论】:

      【解决方案6】:

      我可能理解错了这个问题,但是如果你想声明一个特定形状但里面没有任何东西的数组,以下可能会有所帮助:

      初始化空数组:

      >>> a = np.zeros((0,3)) #or np.empty((0,3)) or np.array([]).reshape(0,3)
      >>> a
      array([], shape=(0, 3), dtype=float64)
      

      现在您可以使用此数组向其追加形状相似的行。请记住,numpy 数组是不可变的,因此每次迭代都会创建一个新数组:

      >>> for i in range(3):
      ...     a = np.vstack([a, [i,i,i]])
      ...
      >>> a
      array([[ 0.,  0.,  0.],
             [ 1.,  1.,  1.],
             [ 2.,  2.,  2.]])
      

      np.vstack 和 np.hstack 是组合 numpy 数组最常用的方法,但来自 Matlab 我更喜欢 np.r_ 和 np.c_:

      连接一维:

      >>> a = np.zeros(0)
      >>> for i in range(3):
      ...     a = np.r_[a, [i, i, i]]
      ...
      >>> a
      array([ 0.,  0.,  0.,  1.,  1.,  1.,  2.,  2.,  2.])
      

      连接行:

      >>> a = np.zeros((0,3))
      >>> for i in range(3):
      ...     a = np.r_[a, [[i,i,i]]]
      ...
      >>> a
      array([[ 0.,  0.,  0.],
             [ 1.,  1.,  1.],
             [ 2.,  2.,  2.]])
      

      连接列:

      >>> a = np.zeros((3,0))
      >>> for i in range(3):
      ...     a = np.c_[a, [[i],[i],[i]]]
      ...
      >>> a
      array([[ 0.,  1.,  2.],
             [ 0.,  1.,  2.],
             [ 0.,  1.,  2.]])
      

      【讨论】:

      • 谢谢您,先生,您是第一个了解 OP 想要什么的人(对我来说似乎很明显),您首先给了我们真正想要的东西。简而言之,是的,当然有一种方法可以连接到一个空数组!再次感谢。
      • 哦,另一种声明“空”数组的方法是a = np.zeros((0,3))
      • 很好,这回答了一个困扰我一段时间的关于最佳方法的问题。谢谢!这确实应该更改为 OP 接受的答案。
      • predictions = np.array([]).reshape(2,2) ValueError: cannot reshape array of size 0 into shape (2,2)
      • @CodePope 对不起,我的意思是,你建议 np.empty 是对的,因为它比整个 reshape 解决方法更干净、更漂亮的代码。您也是正确的,因为它更有效,但是与这种附加方法开始时的糟糕程度相比,效率增益很小。真的,你在这里用 np.empty 没有任何收获。您鼓励我更改代码以使用 np.zeros - i.m.o.最易读/最知名的数组创建函数(效率除外)。
      猜你喜欢
      • 2021-04-15
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-02-21
      • 2021-07-14
      • 1970-01-01
      • 2016-08-19
      • 2018-01-14
      相关资源
      最近更新 更多