32

我正在尝试使用 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)
4

6 回答 6

71

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

初始化空数组:

>>> 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_:

连接 1d:

>>> 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.]])
于 2013-10-31T08:38:52.430 回答
37

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,)。这些形状不匹配,因此您会收到错误消息。

于 2013-10-29T00:10:57.453 回答
3

这是在 Ipython 中运行代码的结果。请注意,这result是一个(2,0)数组,2 行,0 列,0 个元素。append产生一个(2,)数组 。result[0](0,)数组。您的错误消息与尝试将该 2 项数组分配到大小为 0 的插槽有关。由于resultis dtype=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]

手术后你到底想result变成什么样子append

于 2013-10-29T06:04:30.830 回答
3

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

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

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

于 2013-10-29T00:13:43.320 回答
2

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])
于 2013-10-29T00:08:05.327 回答
1

SO线程'将两个数组元素相乘,其中一个数组将数组作为元素'有一个从数组构造数组的示例。如果子数组的大小相同,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())来生成一个二维数组。

于 2013-10-29T16:41:13.777 回答