Concatenating two one-dimensional NumPy arrays

430,867

Solution 1

The line should be:

numpy.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.

Solution 2

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

Solution 3

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

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

Solution 4

An alternative ist to use the short form of "concatenate" which is either "r_[...]" or "c_[...]" as shown in the example code beneath (see http://wiki.scipy.org/NumPy_for_Matlab_Users 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.]]

Solution 5

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])
Share:
430,867
highBandWidth
Author by

highBandWidth

Updated on July 08, 2022

Comments

  • highBandWidth
    highBandWidth almost 2 years

    I have two simple one-dimensional arrays in NumPy. I should be able to concatenate them using numpy.concatenate. But I get this error for the code below:

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

    Code

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

    Why?

  • Hannes Ovrén
    Hannes Ovrén over 10 years
    vector_b = [1,1,1,1] #short form of "array", this is simply not true. vector_b will be a standard Python list type. Numpy is however quite good at accepting sequences instead of forcing all inputs to be numpy.array types.
  • user391339
    user391339 almost 8 years
    thanks! just curious - what is the logic behind this?
  • Winston Ewert
    Winston Ewert almost 8 years
    @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.
  • Jim K.
    Jim K. over 7 years
    @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).
  • Winston Ewert
    Winston Ewert over 7 years
    @JimK. What would happen to the axis parameter?
  • Jim K.
    Jim K. over 7 years
    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.
  • hpaulj
    hpaulj about 7 years
    np.concatentate is a Type: builtin_function_or_method. So the interface is 'hard coded' in numpy compiled code. np.append is a poorly conceived alternative that takes 2 arguments (plus keywords) and puts them in a sequence. The whole range of stack functions also work as concatenate does. So does the ubiquitous np.array. As does the basic Python list().
  • hpaulj
    hpaulj almost 7 years
    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.
  • n1k31t4
    n1k31t4 about 6 years
    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.
  • Ofir Shifman
    Ofir Shifman about 2 years
    thanks! I used you code to check also the influence of the number of arrays (of size 100) and got similar results: i.stack.imgur.com/w6ojK.png