【问题标题】:How does numpy.concatenate work on listsnumpy.concatenate 如何在列表上工作
【发布时间】:2018-12-17 04:56:38
【问题描述】:

我想弄清楚为什么下面的代码不起作用:

import numpy as np

failList = [[[1], [2]],
           [[3, 4, 5, 6], [7]],
           [[8], [9]],
           [[10], [11, 12]],
           [[13], [14, 15, 16]]]

goodList = [[[1], [2], [3, 4, 5, 6], [7], [8]],
           [[9], [10], [11, 12], [13], [14, 15, 16]]]

goodList2 = [[[1], [2], [3, 4, 5, 6], [7], [8]],
            [[9], [10], [11, 12], [13], [14, 15, 16]],
            [[9], [10], [11, 12], [13], [14, 15, 16]]]

myLists = [failList, goodList, goodList]

for l in myLists:
    print([len(l[i]) for i in range(len(l))])
    print([len(l[i][j]) for i in range(len(l)) for j in range(len(l[i]))])
    try:
        np.concatenate(l)
        print("worked")
    except:
        print("failed")

输出是:

[2, 2, 2, 2, 2]
[1, 1, 4, 1, 1, 1, 1, 2, 1, 3]
failed
[5, 5]
[1, 1, 4, 1, 1, 1, 1, 2, 1, 3]
worked
[5, 5, 5]
[1, 1, 4, 1, 1, 1, 1, 2, 1, 3, 1, 1, 2, 1, 3]
worked

谁能解释一下,为什么第一个列表不能连接,而其他列表可以?

【问题讨论】:

  • 它将每个元素变成一个数组。失败案例是 2d 数字和 1d 对象 dtype 的混合

标签: python list numpy concatenation


【解决方案1】:

原答案(错误):

根据docs

数组必须具有相同的形状,除了轴对应的维度(默认为第一个)。

您的第一个列表具有内部列表具有不同长度(分别为 6 和 4)的属性。在您的好列表中,所有内部列表的长度都相同 5。

编辑:抱歉,我没有注意到其中一个括号,所以我错误地将您的failList 的形状视为错误。

正确答案是failList中的子列表有不同的形状

>>> np.array([[1, 2, 3], [4, 5, 6], [7, 8, 9]]).shape
(3,3) # because all lists have the same lengths, so NumPy treats as multi-dim array

>>> np.array([[1, 2, 3], [4, 5, 6], [7, 8, 9, 10]]).shape
(3,) # because all lists have different lengths, so NumPy treats as an array of lists

【讨论】:

  • 什么意思?第一个列表的内部列表的长度都是 2
  • @hyst329 goodList2 = [[[1], [2], [3, 4, 5, 6], [7], [8]], [[9], [10], [11, 12], [13], [14, 15, 16]], [[9], [10], [11, 12], [13], [14, 15, 16,17],[0]]] 内部列表长度为 5, 5, 6 并且串联仍然有效
  • @hyst329 内部列表的长度不一样?对于好的列表,它的 [1, 1, 4, 1, 1, 1, 1, 2, 1, 3]
  • @AljoSt [1, 1, 4, 1, 1] 和 [1, 1, 2, 1, 3] 不同(并非全部相同) .对于失败列表,[1, 1] 相同,但[4, 1] 不同。
  • @Brenlla "Edit:" 上面那一段是错误的,我会特别提一下。
【解决方案2】:

连接元组(或列表)中的列表应该具有相同的维度

您可以在实现np.concatenategithub source code 中看到第399 行。

if (PyArray_NDIM(arrays[iarrays]) != ndim) {
            PyErr_SetString(PyExc_ValueError,
                            "all the input arrays must have same "
                            "number of dimensions");
            return NULL;
}

PyArray_NDIM do 给出所有维度的长度

在您的情况下,failList 中的列表没有相同的维度。 您可以通过以下代码查看。

import numpy as np

failList = [[[1], [2]],
       [[3, 4, 5, 6], [7]],
       [[8], [9]],
       [[10], [11, 12]],
       [[13], [14, 15, 16]]]

goodList = [[[1], [2], [3, 4, 5, 6], [7], [8]],
[[9], [10], [11, 12], [13], [14, 15, 16]]]


goodList2 = [[[1], [2], [3, 4, 5, 6], [7], [8]],
       [[9], [10], [11, 12], [13], [14, 15, 16]],
       [[9], [10], [11, 12], [13], [14, 15, 16]]]

faileShapes = [np.shape(i) for i in failList]
print(faileShapes)

goodShapes = [np.shape(i) for i in goodList]
print(goodShapes)

goodShapes2 = [np.shape(i) for i in goodList2]
print(goodShapes2)

# printed console
# [(2, 1), (2,), (2, 1), (2,), (2,)]
# [(5,), (5,)]
# [(5,), (5,), (5,)]

【讨论】:

    【解决方案3】:

    concatenate 从每个列表元素创建一个数组,然后将这些元素连接到所需的轴上。如果形状不匹配,则会引发错误:

    In [80]: failList = [[[1], [2]],
        ...:            [[3, 4, 5, 6], [7]],
        ...:            [[8], [9]],
        ...:            [[10], [11, 12]],
        ...:            [[13], [14, 15, 16]]]
        ...:            
    In [81]: [np.array(a) for a in failList]
    Out[81]: 
    [array([[1],
            [2]]),
     array([list([3, 4, 5, 6]), list([7])], dtype=object),
     array([[8],
            [9]]),
     array([list([10]), list([11, 12])], dtype=object),
     array([list([13]), list([14, 15, 16])], dtype=object)]
    In [82]: [np.array(a).shape for a in failList]
    Out[82]: [(2, 1), (2,), (2, 1), (2,), (2,)]
    In [83]: np.concatenate([np.array(a) for a in failList])
    ---------------------------------------------------------------------------
    ValueError                                Traceback (most recent call last)
    <ipython-input-83-c3434632bd7e> in <module>()
    ----> 1 np.concatenate([np.array(a) for a in failList])
    
    ValueError: all the input arrays must have same number of dimensions
    

    failedList 的元素用于不同类型的数组,有些是二维数字,有些是一维对象。 concatenate 不能加入。

    column_stack 确实有效:

    In [87]: np.column_stack(failList)
    Out[87]: 
    array([[1, list([3, 4, 5, 6]), 8, list([10]), list([13])],
           [2, list([7]), 9, list([11, 12]), list([14, 15, 16])]],
          dtype=object)
    In [88]: _.shape
    Out[88]: (2, 5)
    

    这是因为它将 (2,) 形状的数组重塑为 (2,1)。现在它有一个包含 5 个 (2,1) 数组的列表,它可以在第 2 维上连接这些数组,从而生成一个 (2,5) 数组。但请注意,它是对象 dtype。有些元素是整数,有些是列表(大小不同)。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2020-11-01
      • 1970-01-01
      • 2022-07-29
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-09-08
      相关资源
      最近更新 更多