【问题标题】:Numpy broadcast shape error: convert list( lists(arrays) ) to arrayNumpy广播形状错误:将列表(列表(数组))转换为数组
【发布时间】:2017-10-19 16:12:43
【问题描述】:

我有一个列表列表,例如 list_ABC = [[A,B,C], [A,B,C], ...]
使用 2D ndarrays A (2x2)、B (2x3) 和 C (2x3)。

现在,我想将主列表转换为 numpy 数组:

np.array(list_ABC)

但是,我收到以下错误:

ValueError: could not broadcast input array from shape (2,2) into shape (2)

我需要这种转换,因为我想得到

A_matrices = np.array(list_ABC)[:, 0]
B_matrices = np.array(list_ABC)[:, 1]

这样我终于可以得到一个包含所有A-arrays(array(A,A,A,...))的ndarray了。

不幸的是,我无法从值错误消息中获得线索。有趣的是,如果我只用 C.T 转置矩阵 C(使其成为 3x2 矩阵),则不会引发错误。

现在,我可以通过预先创建 list_A、list_B、list_C(而不是 list_ABC)来解决问题,但这感觉并不简单(构造和附加到每个 list_A/B/C 需要多几行代码)。同样,我可以使用其他方法(例如,使用带有 A、B、C 键的 dict,其中包含所有 A/B/C 矩阵的列表),但没有什么比这个解决方案更简单了。

抛出错误的工作示例:

import numpy as np
list = [[np.array([[ 476.,  667.], [ 474.,  502.]]), np.array([[ 343.,  351.,  449.], [ 352.,  332.,  292.]]), np.array([[ 328.,  328.,  294.], [ 367.,  355.,  447.]])], [np.array([[ 497.,  546.], [ 456.,  517.]]), np.array([[ 361.,  342.,  340.], [ 341.,  304.,  328.]]), np.array([[ 347.,  313.,  293.], [ 355.,  333.,  375.]])]]
np.array(list)

非常感谢!

【问题讨论】:

  • 我认为是因为有些数组有两个元素,有些是三个!
  • 是的,如果示例中的所有数组都是 2x3,那么它可以工作。
  • 不幸的是,数组需要具有这些尺寸。正如所写,如果我只转置 C,它会以某种方式工作?
  • 似乎这与 np.array 如何尝试制作新的数组有关。如果您使用 C.T,或者将它们全部设为 2x3 或全部 3x3,然后查看形状,您要么得到 2D 数组,要么得到 4D 数组。我猜这就是当 A 的列与 C 的列不匹配时抛出错误的原因
  • 如果形状匹配,则从其他数组构造数组创建更高维数组,如果不匹配则创建对象 dtype 数组,或者对于某些类型的不匹配抛出此错误。

标签: python arrays numpy


【解决方案1】:

从数组构造数组时,np.array 函数可以做 3 件事:

  • 如果所有子数组都具有相同的形状,它将构成一个更高维的数组

  • 如果子数组的形状不同,它可能会构造一个对象 dtype 数组。这就像一个列表或嵌套列表,但能够像数组一样索引和重塑

  • 引发错误。当行匹配但列不匹配时,这似乎最常发生。它可能检测到形状不匹配为时已晚,无法依靠对象 dtype 解决方案。

更多信息请访问:

How to keep numpy from broadcasting when creating an object array of different shaped arrays


要获得array(A,A,A,...),我建议使用列表理解。构造对象 dtype 数组太棘手了。


创建对象数组的可靠方法是初始化一个空的并填充它:

In [116]: arr = np.empty((2,3), dtype=object)
In [117]: arr[...] = alist
In [118]: arr
Out[118]: 
array([[array([[ 476.,  667.],
       [ 474.,  502.]]),
        array([[ 343.,  351.,  449.],
       [ 352.,  332.,  292.]]),
        array([[ 328.,  328.,  294.],
       [ 367.,  355.,  447.]])],
       [array([[ 497.,  546.],
       [ 456.,  517.]]),
        array([[ 361.,  342.,  340.],
       [ 341.,  304.,  328.]]),
        array([[ 347.,  313.,  293.],
       [ 355.,  333.,  375.]])]], dtype=object)

现在我可以选择“A”元素了:

In [119]: arr[:,0]
Out[119]: 
array([array([[ 476.,  667.],
       [ 474.,  502.]]),
       array([[ 497.,  546.],
       [ 456.,  517.]])], dtype=object)

但这是一个对象数组,再次包装在 np.array 中并不会改变这一点:

In [120]: np.array(arr[:,0])
Out[120]: 
array([array([[ 476.,  667.],
       [ 474.,  502.]]),
       array([[ 497.,  546.],
       [ 456.,  517.]])], dtype=object)

但它们可以连接在几个不同的轴上。

In [121]: np.stack(arr[:,0])
Out[121]: 
array([[[ 476.,  667.],
        [ 474.,  502.]],

       [[ 497.,  546.],
        [ 456.,  517.]]])

但我可以在没有对象数组步骤的情况下得到同样的结果

In [123]: np.stack([a[0] for a in alist])
Out[123]: 
array([[[ 476.,  667.],
        [ 474.,  502.]],

       [[ 497.,  546.],
        [ 456.,  517.]]])

【讨论】:

  • 非常感谢您的详细解释!列表推导方法非常简单易用:)
猜你喜欢
  • 1970-01-01
  • 2017-03-08
  • 2019-08-30
  • 1970-01-01
  • 2015-01-07
  • 2021-06-09
  • 1970-01-01
  • 2019-06-11
相关资源
最近更新 更多