【问题标题】:Concatenating two one-dimensional NumPy arrays连接两个一维 NumPy 数组
【发布时间】:2012-03-03 11:05:30
【问题描述】:

我在NumPy 中有两个简单的一维数组。我应该能够使用numpy.concatenate 连接它们。但我收到以下代码的此错误:

TypeError: 只有长度为 1 的数组可以转换为 Python 标量

代码

import numpy
a = numpy.array([1, 2, 3])
b = numpy.array([5, 6])
numpy.concatenate(a, b)

为什么?

【问题讨论】:

  • 如果您想将它们沿一个轴串联(成一个数组),请使用np.concatenat(..., axis)。如果要垂直堆叠它们,请使用np.vstack。如果要将它们水平堆叠(成多个数组),请使用np.hstack。 (如果您想按深度堆叠它们,即第 3 维,请使用 np.dstack)。注意后者类似于pandaspd.concat

标签: python arrays numpy concatenation numpy-ndarray


【解决方案1】:

该行应该是:

numpy.concatenate([a,b])

您要连接的数组需要作为一个序列传入,而不是作为单独的参数。

来自NumPy documentation

numpy.concatenate((a1, a2, ...), axis=0)

将一系列数组连接在一起。

它试图将您的 b 解释为轴参数,这就是它抱怨无法将其转换为标量的原因。

【讨论】:

  • 谢谢!只是好奇——这背后的逻辑是什么?
  • @user391339,如果你想连接三个数组怎么办?如果只使用两个数组,则该函数在获取序列时更有用。
  • @WinstonEwert 假设问题不在于它被硬编码为两个参数,如果您愿意,您可以像 numpy.concatenate(a1, a2, a3)numpy.concatenate(*[a1, a2, a3]) 一样使用它。 Python 足够流畅,以至于差异最终感觉更像是表面上的,而不是实质上的,但是当 API 保持一致时(例如,如果所有采用可变长度参数列表的 numpy 函数都需要显式序列)。
  • @JimK。轴参数会发生什么?
  • 假设要连接的东西都是位置参数,您可以将轴保留为关键字参数,例如def concatx(*sequences, **kwargs))。这并不理想,因为您似乎无法以这种方式在签名中明确命名关键字 args,但有一些解决方法。
【解决方案2】:

连接一维数组有多种可能性,例如,

numpy.r_[a, a],
numpy.stack([a, a]).reshape(-1),
numpy.hstack([a, a]),
numpy.concatenate([a, a])

所有这些选项对于大型数组都同样快;对于小的,concatenate 有一点优势:

情节是用perfplot创建的:

import numpy
import perfplot

perfplot.show(
    setup=lambda n: numpy.random.rand(n),
    kernels=[
        lambda a: numpy.r_[a, a],
        lambda a: numpy.stack([a, a]).reshape(-1),
        lambda a: numpy.hstack([a, a]),
        lambda a: numpy.concatenate([a, a]),
    ],
    labels=["r_", "stack+reshape", "hstack", "concatenate"],
    n_range=[2 ** k for k in range(19)],
    xlabel="len(a)",
)

【讨论】:

  • 替代品都使用np.concatenate。他们只是事先以各种方式按摩输入列表。 np.stack 例如为所有输入数组添加一个额外的维度。看看他们的源代码。仅编译 concatenate
  • 只是为了添加到 @hpaulj 的评论中 - 随着数组大小的增长,所有时间都会收敛,因为 np.concatenate 会复制输入。这种内存和时间成本超过了“按摩”输入所花费的时间。
【解决方案3】:

concatenate 的第一个参数本身应该是一个数组序列来连接:

numpy.concatenate((a,b)) # Note the extra parentheses.

【讨论】:

    【解决方案4】:

    另一种方法是使用“连接”的缩写形式,即“r_[...]”或“c_[...]”,如下面的示例代码所示(有关更多信息,请参阅http://wiki.scipy.org/NumPy_for_Matlab_Users ):

    %pylab
    vector_a = r_[0.:10.] #short form of "arange"
    vector_b = array([1,1,1,1])
    vector_c = r_[vector_a,vector_b]
    print vector_a
    print vector_b
    print vector_c, '\n\n'
    
    a = ones((3,4))*4
    print a, '\n'
    c = array([1,1,1])
    b = c_[a,c]
    print b, '\n\n'
    
    a = ones((4,3))*4
    print a, '\n'
    c = array([[1,1,1]])
    b = r_[a,c]
    print b
    
    print type(vector_b)
    

    结果:

    [ 0.  1.  2.  3.  4.  5.  6.  7.  8.  9.]
    [1 1 1 1]
    [ 0.  1.  2.  3.  4.  5.  6.  7.  8.  9.  1.  1.  1.  1.] 
    
    
    [[ 4.  4.  4.  4.]
     [ 4.  4.  4.  4.]
     [ 4.  4.  4.  4.]] 
    
    [[ 4.  4.  4.  4.  1.]
     [ 4.  4.  4.  4.  1.]
     [ 4.  4.  4.  4.  1.]] 
    
    
    [[ 4.  4.  4.]
     [ 4.  4.  4.]
     [ 4.  4.  4.]
     [ 4.  4.  4.]] 
    
    [[ 4.  4.  4.]
     [ 4.  4.  4.]
     [ 4.  4.  4.]
     [ 4.  4.  4.]
     [ 1.  1.  1.]]
    

    【讨论】:

    • vector_b = [1,1,1,1] #short form of "array",这根本不是真的。 vector_b 将是标准的 Python 列表类型。然而,Numpy 非常擅长接受序列,而不是强制所有输入为 numpy.array 类型。
    • 你是对的——我错了。我更正了我的源代码以及结果。
    【解决方案5】:

    这里有更多方法可以使用numpy.ravel()numpy.array(),利用一维数组可以解压缩为普通元素的事实:

    # we'll utilize the concept of unpacking
    In [15]: (*a, *b)
    Out[15]: (1, 2, 3, 5, 6)
    
    # using `numpy.ravel()`
    In [14]: np.ravel((*a, *b))
    Out[14]: array([1, 2, 3, 5, 6])
    
    # wrap the unpacked elements in `numpy.array()`
    In [16]: np.array((*a, *b))
    Out[16]: array([1, 2, 3, 5, 6])
    

    【讨论】:

      【解决方案6】:

      更多来自 numpy docs 的事实:

      语法为numpy.concatenate((a1, a2, ...), axis=0, out=None)

      axis = 0 表示逐行连接 axis = 1 表示按列连接

      >>> a = np.array([[1, 2], [3, 4]])
      >>> b = np.array([[5, 6]])
      
      # Appending below last row
      >>> np.concatenate((a, b), axis=0)
      array([[1, 2],
             [3, 4],
             [5, 6]])
      
      # Appending after last column
      >>> np.concatenate((a, b.T), axis=1)    # Notice the transpose
      array([[1, 2, 5],
             [3, 4, 6]])
      
      # Flattening the final array
      >>> np.concatenate((a, b), axis=None)
      array([1, 2, 3, 4, 5, 6])
      

      希望对你有帮助!

      【讨论】:

        猜你喜欢
        • 2017-08-12
        • 1970-01-01
        • 1970-01-01
        • 2021-05-02
        • 2011-05-08
        • 2017-08-18
        • 1970-01-01
        • 2020-01-03
        相关资源
        最近更新 更多