【问题标题】:Using numpy for first time hit "ValueError: zero-dimensional arrays cannot be concatenated"首次使用 numpy 命中“ValueError:无法连接零维数组”
【发布时间】:2018-01-22 00:28:33
【问题描述】:

今天我安装了我的第一个包 numpy,并想尝试一下。所以我发现 这篇文章,Bayes’ theorem implementation in python,想尝试一下。我遇到了一个错误:

代码:

import numpy as np

x_red = np.array([1,2,3])

y_red = np.array([1,2,3])

z_red = np.array([1,2,3])

red_points = np.array(zip(x_red,y_red,z_red))

x_blue = np.array([1,2,3])

y_blue = np.array([1,2,3])

z_blue = np.array([1,2,3])

blue_points = np.array(zip(x_blue,y_blue,z_blue))

points = np.concatenate([red_points,blue_points])

最后一行出现错误:

Traceback (most recent call last):
  File "C:\Users\Mike\AppData\Local\Programs\Python\Python36-32\tmp.py", line 19, in <module>
    points = np.concatenate([red_points,blue_points])
ValueError: zero-dimensional arrays cannot be concatenated

我现在希望将 numpy 作为黑盒运行,但作为 python 新手不知道如何调试“包错误”。

可能是 python 3.6 发生了一些变化(代码使用了旧的 print 语句)。

任何答案/cmets 将不胜感激。

【问题讨论】:

  • 尝试在没有 zip 的情况下创建 red_points。检查它的形状。

标签: python python-3.x numpy concatenation


【解决方案1】:

您需要在zip 函数上调用list。在 python 3 zip 返回一个迭代器。

这里:

import numpy as np
x_red = np.array([1,2,3])
y_red = np.array([1,2,3])
z_red = np.array([1,2,3])
red_points = np.array(list(zip(x_red,y_red,z_red)))  # <- here
x_blue = np.array([1,2,3])
y_blue = np.array([1,2,3])
z_blue = np.array([1,2,3])
blue_points = np.array(list(zip(x_blue,y_blue,z_blue)))  # <- and here
points = np.concatenate([red_points,blue_points])

【讨论】:

  • 为什么np.array 接受这样的迭代器却没有任何用处?
  • 我想这是有充分理由的。但恐怕我不是要问的人
  • 这似乎是 hpaulj 的回答中提到的空形(0维)案例。我想将标量作为数组的特例很好,但它并不一致:例如,np.array(1)+np.array(3) 产生np.int64(4)
  • @DavisHerring 干得好,是的,这很奇怪,为什么不返回一个数组?有趣!
  • 1np.int32(1)np.array(1) 之间存在一定的重叠,但它们并不完全相同。类一开始就不同,可用的方法也不同。
【解决方案2】:

np.array 接受像列表一样的可迭代对象,但不接受迭代器或生成器。

In [26]: red_points = np.array(zip(x_red,y_red,z_red)) 
In [27]: red_points
Out[27]: array(<zip object at 0xab7d9b2c>, dtype=object)

结果是一个 0d 数组,其中包含一个项目,即 zip 对象。在 Py2 中,zip 产生了一个列表,在 Py3 中你必须 list 它。

In [28]: red_points = np.array(list(zip(x_red,y_red,z_red)))
In [29]: red_points
Out[29]: 
array([[1, 1, 1],
       [2, 2, 2],
       [3, 3, 3]])

np.array(...) 采用类似Out[29] 中显示的列表列表。这是最常见的使用方式之一。

像这样使用zip(...) 实际上是一种转置输入的方法。 numpy 也可以转置:

In [31]: red_points = np.array((x_red,y_red,z_red))
In [32]: red_points
Out[32]: 
array([[1, 2, 3],
       [1, 2, 3],
       [1, 2, 3]])
In [33]: red_points.T
Out[33]: 
array([[1, 1, 1],
       [2, 2, 2],
       [3, 3, 3]])

np.stack 也可以。使用默认的axis=0,它的行为就像np.array

In [34]: red_points = np.stack((x_red,y_red,z_red),axis=1)
In [35]: red_points
Out[35]: 
array([[1, 1, 1],
       [2, 2, 2],
       [3, 3, 3]])

虽然 0d 数组并不常见,但当它们出现时有助于理解它们。养成在遇到错误或意外结果时检查数组的shapedtype 的习惯。


有一个 fromiter 可以与迭代器一起使用,但它需要一个 dtype - 并且只生成一个一维数组。

In [39]: np.fromiter(zip(x_red,y_red,z_red),'i,i,i')
Out[39]: 
array([(1, 1, 1), (2, 2, 2), (3, 3, 3)],
      dtype=[('f0', '<i4'), ('f1', '<i4'), ('f2', '<i4')])

np.array 期望完整列表的部分原因在于,它会在决定 dtype 和 shape 之类的内容之前查看整个内容。

【讨论】:

  • 谢谢。当 print(red_points,red_points.shape,red_points.dtype) 这样的语句起作用时,当然更容易看到 numpy 在做什么!
  • red_points = np.stack([x_red,y_red,z_red],axis=1) 有效,是一个“干净”的替代方案。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-08-15
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-05-08
相关资源
最近更新 更多