未成功追加到空 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
只是一个concatenate
:return 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)
a
和b
的形状需要匹配。如果你附加一个 (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 的插槽有关。由于result
是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
操作后是什么样子?
【讨论】:
投票。但是我认为您已经写的内容已包含在其他答案中。还是谢谢【参考方案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 数组的主要内容,如果未能解决你的问题,请参考以下文章