422

How do I concatenate two one-dimensional arrays in NumPy? I tried numpy.concatenate:

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

But I get an error:

TypeError: only length-1 arrays can be converted to Python scalars

1
  • 7
    If you want to concatenate them (into a single array) along an axis, use np.concatenat(..., axis). If you want to stack them vertically, use np.vstack. If you want to stack them (into multiple arrays) horizontally, use np.hstack. (If you want to stack them depth-wise, i.e. teh 3rd dimension, use np.dstack). Note that the latter are similar to pandas pd.concat Commented Apr 29, 2020 at 2:52

7 Answers 7

561

Use:

np.concatenate([a, b])

The arrays you want to concatenate need to be passed in as a sequence, not as separate arguments.

From the NumPy documentation:

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

Join a sequence of arrays together.

It was trying to interpret your b as the axis parameter, which is why it complained it couldn't convert it into a scalar.

Sign up to request clarification or add additional context in comments.

6 Comments

thanks! just curious - what is the logic behind this?
@user391339, what if you wanted to concatenate three arrays? The function is more useful in taking a sequence then if it just took two arrays.
@WinstonEwert Assuming the issue isn't that it's hardcoded to two arguments, you could use it like numpy.concatenate(a1, a2, a3) or numpy.concatenate(*[a1, a2, a3]) if you prefer. Python's fluid enough that the difference ends up feeling more cosmetic than substantial, but it's good when the API is consistent (e.g. if all the numpy functions that take variable length argument lists require explicit sequences).
@JimK. What would happen to the axis parameter?
Assuming the things to concatenate are all positional parameters, you could keep axis as a keyword argument e.g. def concatx(*sequences, **kwargs)). It's not ideal since you can't seem to name the keyword args explicitly in the signature this way, but there are workarounds.
|
87

There are several possibilities for concatenating 1D arrays, e.g.,

import numpy as np

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

All those options are equally fast for large arrays; for small ones, concatenate has a slight edge:

enter image description here

The plot was created with 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)",
)

4 Comments

The alternatives all use np.concatenate. They just massage the input list in various ways before hand. np.stack for example adds an extra dimension to all input arrays. Look at their source code. Only concatenate is compiled.
Just to add to @hpaulj 's comment - the times all converge as the size of the arrays grows because the np.concatenate makes copies of the inputs. This memory and time cost then outweighs the time spent 'massaging' the input.
thanks! I used you code to check also the influence of the number of arrays (of size 100) and got similar results: i.sstatic.net/w6ojK.png
I didn't know about perfplot, really handy.
41

The first parameter to concatenate should itself be a sequence of arrays to concatenate:

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

Comments

15

An alternative ist to use the short form of "concatenate" which is either "r_[...]" or "c_[...]" as shown in the example code beneath (see Link for additional information):

%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)

Which results in:

[ 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.]]

Comments

4

Some more facts from the numpy docs :

With syntax as numpy.concatenate((a1, a2, ...), axis=0, out=None)

axis = 0 for row-wise concatenation axis = 1 for column-wise concatenation

>>> 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])

I hope it helps !

Comments

2

Here are more approaches for doing this by using numpy.ravel(), numpy.array(), utilizing the fact that 1D arrays can be unpacked into plain elements:

# 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])

Comments

0

Slightly different problem, that is if you want two 1D array with shape (n,) into (2,n), then you have the following options:

import numpy as np

np.r_[[a], [a]]
np.stack([a, a])
np.vstack([a, a])
np.concatenate([[a], [a]])
np.array([a, a])

The fastest way is to use plain numpy.array:

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]),
        lambda a: numpy.vstack([a, a]),
        lambda a: numpy.concatenate([[a], [a]]),
        lambda a: numpy.array([a, a]),
    ],
    labels=["r_", "stack", "vstack", "concatenate", "array"],
    n_range=[2 ** k for k in range(19)],
    xlabel="len(a)",
)

enter image description here

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.