未成功追加到空 NumPy 数组

Posted

技术标签:

【中文标题】未成功追加到空 NumPy 数组【英文标题】:Unsuccessful append to an empty NumPy array 【发布时间】: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)

【问题讨论】:

【参考方案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.最易读/最知名的数组创建函数(效率除外)。

以上是关于未成功追加到空 NumPy 数组的主要内容,如果未能解决你的问题,请参考以下文章

将空行插入或追加到 numpy 数组

在追加模式下加载使用 numpy.save 保存的数组

Python Numpy追加数组而不展平

有没有办法在没有numpy的情况下追加二维数组?

创建一个基于空的numpy数组并附加现有数组

追加 Python 3D Numpy 数组