连接两个一维NumPy数组


266

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

TypeError:只有length-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)。请注意,后者类似于熊猫pd.concat
smci

Answers:


372

该行应为:

numpy.concatenate([a,b])

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

NumPy文档中

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

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

它试图将您解释b为axis参数,这就是为什么它抱怨无法将其转换为标量。


1
谢谢!只是好奇-这背后的逻辑是什么?
user391339

8
@ user391339,如果要串联三个数组怎么办?如果仅获取两个数组,则该函数在获取序列时更有用。
Winston Ewert

@WinstonEwert假设问题不在于它的硬编码到两个参数,你可以使用它像numpy.concatenate(a1, a2, a3)或者numpy.concatenate(*[a1, a2, a3])如果你喜欢。Python的流畅性足以使差异最终看起来比实质要美观,但如果API保持一致(例如,所有采用可变长度参数列表的numpy函数都需要显式序列),则很好。
Jim K.

@JimK。轴参数会怎样?
温斯顿·埃韦特

1
假设要连接的东西都是位置参数,则可以将axis保留为关键字参数,例如def concatx(*sequences, **kwargs))。这并不理想,因为您似乎无法以这种方式在签名中显式命名关键字args,但是有一些解决方法。
Jim K.

37

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

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)",
)

9
替代品全部使用np.concatenate。他们只是在事前以各种方式对输入列表进行按摩。 np.stack例如,向所有输入数组添加额外的维度。看他们的源代码。仅concatenate被编译。
hpaulj

1
只是要添加到@hpaulj的注释中-所有时间都随着数组大小的增长而收敛,这是因为要np.concatenate复制输入。这样,此内存和时间成本就超过了“按摩”输入所花费的时间。
n1k31t4

31

的第一个参数concatenate本身应该是要串联的数组序列

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

10

另一种方法是使用“ concatenate”的缩写形式,即“ 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.]]

2
vector_b = [1,1,1,1] #short form of "array", 这是不正确的。vector_b将是标准的Python列表类型。但是,Numpy非常擅长接受序列,而不是强制所有输入为numpy.array类型。
汉尼斯·奥夫雷恩(HannesOvrén)2013年

2
你是对的-我错了。我更正了源代码和结果。
SemjonMössinger13年

0

以下是使用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])

0

来自numpy 文档的更多事实:

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

轴= 0用于行连接轴= 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])

希望对您有所帮助!

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.