【问题标题】:Why Can't Numpy Produce an Array from a List of Numpy Arrays?为什么 Numpy 不能从 Numpy 数组列表中生成数组?
【发布时间】:2022-01-16 00:28:14
【问题描述】:

我正在编写一些代码来按向量之间的角度对向量进行分组。例如,我可能有一个向量数组:

vectors = np.array([[1, 0, 0], [1.1, 0, 0], [0, 2, 2]])

例如,可接受的角度偏差为 0.1 弧度。目前,我正在像这样的 while 循环中执行此操作:

groups = []
while not vectors.size == 0:
    vector = vectors[0]
    angles = (vectors @ vector)/(np.linalg.norm(vector, axis=1))
    angles = np.arccos(angles/np.linalg.norm(vector))
    group = vectors[angles <= angle]
    groups.append(group)
    vectors = vectors[angles > angle]
return np.array(groups)

我希望这会返回一个具有以下形式的 numpy 数组:

expected_array = np.array([[[1, 0, 0], [1.1, 0, 0]], [[0, 2, 2]]])

但我得到以下信息:

actual_array = np.array([array([[1. , 0. , 0. ], [1.1, 0. , 0. ]]),
                         array([[0. , 2, 2]])])

为什么 Numpy 没有注意到列表包含数组并给出我期望的结果?有没有办法让 Numpy 注意到这一点?还是您总是必须使用 np.concatenate 或类似的东西才能获得所需的结果?

【问题讨论】:

  • 数组和列表真的有区别吗?有什么你不能做的吗?
  • 看起来数组列表可能是最适合您的用例的数据结构。您想要的输出似乎丢弃了作为代码全部目的的分组信息。
  • np.array can't read your mind` 问题在于你的期望。但是np.vstack(groups) 可能会做你想做的事。
  • @user2357112supportsMonica 我认为您实际上可能是对的,但我仍然对如何达到预期结果感兴趣。如果只是为了知道将来该怎么做。它并没有真正破坏我的分组,它只是让使用数组变得更加困难,但也许还有速度的额外好处?
  • @Chris 对于一个小的用例,不,它没有区别,实际上可能是有益的。但我想我在想,如果我有数百万个向量,我指定的形式的返回数组对于未来的计算是否会更快。比如说矢量比较。

标签: python arrays python-3.x list numpy


【解决方案1】:

“我希望这会返回一个具有以下形式的 numpy 数组:”

In [420]: np.array([[[1, 0, 0], [1.1, 0, 0]], [[0, 2, 2]]])
<ipython-input-420-a1f3305ab5c3>:1: VisibleDeprecationWarning: Creating an ndarray from ragged nested sequences (which is a list-or-tuple of lists-or-tuples-or ndarrays with different lengths or shapes) is deprecated. If you meant to do this, you must specify 'dtype=object' when creating the ndarray. np.array([[[1, 0, 0], [1.1, 0, 0]], [[0, 2, 2]]])

Out[420]: array([list([[1, 0, 0], [1.1, 0, 0]]), list([[0, 2, 2]])], dtype=object)

这真的是你所期望的吗?保留列表嵌套的数组?

vstack(或concatenate)可以将列表/数组与列表连接起来,形成一个二维数组:

In [421]: np.vstack([[[1, 0, 0], [1.1, 0, 0]], [[0, 2, 2]]])
Out[421]: 
array([[1. , 0. , 0. ],
       [1.1, 0. , 0. ],
       [0. , 2. , 2. ]])

这是唯一可用于快速编译方法的版本。对象 dtype 数组在进行计算时对元素使用 python 速度迭代。从计算上讲,创建“参差不齐”的数组几乎没有优势。

将这 2 个数组转换回列表:

In [422]: _420.tolist()
Out[422]: [[[1, 0, 0], [1.1, 0, 0]], [[0, 2, 2]]]
In [423]: _421.tolist()
Out[423]: [[1.0, 0.0, 0.0], [1.1, 0.0, 0.0], [0.0, 2.0, 2.0]]

第一个有3层嵌套,和原来一样;第二个只有 2 个。

===

您的代码无法运行:

In [424]: vectors = np.array([[1, 0, 0], [1.1, 0, 0], [0, 2, 2]])
In [425]: groups = []
     ...: while not vectors.size == 0:
     ...:     vector = vectors[0]
     ...:     angles = (vectors @ vector)/(np.linalg.norm(vector, axis=1))
     ...:     angles = np.arccos(angles/np.linalg.norm(vector))
     ...:     group = vectors[angles <= angle]
     ...:     groups.append(group)
     ...:     vectors = vectors[angles > angle]
     ...: 
Traceback (most recent call last):
  File "<ipython-input-425-e50fafbda1c3>", line 4, in <module>
    angles = (vectors @ vector)/(np.linalg.norm(vector, axis=1))
  File "<__array_function__ internals>", line 5, in norm
  File "/usr/local/lib/python3.8/dist-packages/numpy/linalg/linalg.py", line 2561, in norm
    return sqrt(add.reduce(s, axis=axis, keepdims=keepdims))
AxisError: axis 1 is out of bounds for array of dimension 1

在您尝试从中创建数组之前,我希望看到列表 groups。我不想调试你的示例。

【讨论】:

    【解决方案2】:

    简而言之:可以! (但不是你想要的方式。)

    围绕这个主题搜索发现这个问题:Numpy stack with unequal shapes

    其中明确了以下内容:numpy 数组必须是矩形的,因为上面的例子加在一起不会产生矩形数组,这是行不通的。

    如果您尝试对相同大小的数组做同样的事情,它会起作用。例如:

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

    将产生一个形状为 (2, 3) 的数组。

    但是,对于不同大小的数组,numpy 数组 dtype 默认为 object,并且所有单独的数组都会被存储。

    【讨论】:

      猜你喜欢
      • 2016-08-23
      • 2022-01-25
      • 1970-01-01
      • 2017-03-08
      • 1970-01-01
      • 2021-02-13
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多