26

I am trying to concatenate two numpy arrays to add an extra column: array_1 is (569, 30) and array_2 is is (569, )

combined = np.concatenate((array_1, array_2), axis=1)

I thought this would work if I set axis=2 so it will concatenate vertically. The end should should be a 569 x 31 array.

The error I get is ValueError: all the input arrays must have same number of dimensions

Can someone help?

Thx!

3
  • Close, but you have only two axis (axis 0 = 569 and axis 1 = 30), try axis=1. Commented Oct 12, 2017 at 1:45
  • hi - that was a typo.. i just updated my question with my array's shapes and the error i get back Commented Oct 12, 2017 at 1:48
  • 3
    Ahh your array_2 only has one dimension, needs to have same number of dimensions with your array_1. You can either reshape it array_2.reshape(-1,1), or add a new axis array_2[:,np.newaxis] to make it 2 dimensional before concatenation. Commented Oct 12, 2017 at 1:53

5 Answers 5

34

You can use numpy.column_stack:

np.column_stack((array_1, array_2))

Which converts the 1-d array to 2-d implicitly, and thus equivalent to np.concatenate((array_1, array_2[:,None]), axis=1) as commented by @umutto.


a = np.arange(6).reshape(2,3)
b = np.arange(2)

a
#array([[0, 1, 2],
#       [3, 4, 5]])

b
#array([0, 1])

np.column_stack((a, b))
#array([[0, 1, 2, 0],
#       [3, 4, 5, 1]])
Sign up to request clarification or add additional context in comments.

2 Comments

It uses array(arr, copy=False, subok=True, ndmin=2).T to convert a 1d array into 2. I like your [:, None] better. :)
What will be the equivalent if we want to achieve axis=-1 of the same ?
0

You can simply use numpy's hstack function.

e.g.

import numpy as np

combined = np.hstack((array1,array2))

Comments

0

To stack them vertically try

np.vstack((array1,array2))

Comments

0

You can convert the 1-D array to 2-D array with the same number of rows using reshape function and concatenate the resulting array horizontally using numpy's append function.

Note: In numpy's append function, we have to mention axis along which we want to insert the values. If axis=0, arrays are appended vertically. If axis=1, arrays are appended horizontally. So, we can use axis=1, for current requirement

e.g.

a = np.arange(6).reshape(2,3)
b = np.arange(2)

a
#array([[0, 1, 2],
#       [3, 4, 5]])

b
#array([0, 1])

#First step, convert this 1-D array to 2-D (Number of rows should be same as array 'a' i.e. 2)
c = b.reshape(2,1)

c
#array([[0],
        [1]])


#Step 2, Using numpy's append function we can concatenate both arrays with same number of rows horizontally

requirement = np.append((a, c, axis=1))

requirement
#array([[0, 1, 2, 0],
#       [3, 4, 5, 1]])

Comments

0

I have written a general stacking function. It is a bit more complicated but its inputs are just the arrays (tuple) and an axis along which you wish to stack the arrays. E.g.

A = np.random.random((569, 30))
B = np.random.random((569,))
C = stack((A, B), axis=1)  # C.shape == (569, 31)



def stack(arrays: tuple | list, axis: int | None = None, reduce: bool = False) -> np.ndarray:
    """
    concatenate arrays along the specific axis

    if reduce=True, the "arrays" tuple is processed in this way
    arrays = (A, B, C, D)
    stack((stack((stack((A, B), axis=axis), C), axis=axis), D), axis=axis)
    This is potentially slower but allows to concatenate e.g.
    A.shape = (2, 4, 4)
    B.shape = (3, 4)
    C.shape = (4,)
    res = stack((C, B, A), axis=0, reduce=True)
    res.shape = (3, 4, 4)
    res[0] == stack((C, B), axis=0)
    res[1:] == A
    """

    @reduce_like
    def _stack(arrays: tuple | list, axis: int | None = None) -> np.ndarray:
        ndim = np.array([np.ndim(array) for array in arrays])
        _check_dims(ndim, reduce)

        if np.all(ndim == 1):  # vector + vector + ...
            if axis is None:  # -> vector
                return np.concatenate(arrays, axis=axis)
            else:  # -> 2-D array
                return np.stack(arrays, axis=axis)

        elif np.var(ndim) != 0:  # N-D array + (N-1)-D array + ... -> N-D array
            max_dim = np.max(ndim)

            # longest array
            shape = list(np.shape(arrays[np.argmax(ndim)]))
            shape[axis] = -1

            arrays = [np.reshape(a, shape) if np.ndim(a) < max_dim else a for a in arrays]
            return np.concatenate(arrays, axis=axis)

        elif is_constant(ndim):  # N-D array + N-D array + -> N-D array or (N+1)-D array
            ndim = ndim[0]
            if axis < ndim:  # along existing dimensions
                return np.concatenate(arrays, axis=axis)
            else:  # along a new dimension
                return np.stack(arrays, axis=axis)

    def _check_dims(ndim: np.ndarray, reduce: bool = False) -> None:
        error_msg = "Maximum allowed difference in dimension of concatenated arrays is one."

        if np.max(ndim) - np.min(ndim) > 1:
            if reduce:
                raise ValueError(error_msg)
            else:
                raise ValueError(f'{error_msg}\nUse "reduce=True" to unlock more general (but slower) stacking.')

    # 0-D arrays to 1-D arrays (to e.g. add a number to a vector)
    arrays = tuple([np.reshape(array, (1,)) if np.ndim(array) == 0 else array for array in arrays])

    if reduce:
        return _stack(arrays, axis)
    else:
        return _stack.undecorated(arrays, axis)
        
        
def is_constant(array: np.ndarray, axis: int | bool = None, constant: float = None) -> bool | np.ndarray:
    if constant is None:  # return True if the array is constant along the axis
        return np.var(array, axis=axis) < _num_eps
    else:  # return True if the array is equal to "constant" along the axis
        return np.all(np.abs(array - constant) < _num_eps, axis=axis)
        
        
def reduce_like(func: Callable):
    @wraps(func)
    def _decorator(*args, **kw):
        args = list(args)
        arrays = args[0]
        result = arrays[0]

        for array in arrays[1:-1]:
            if args[1:]:
                new_args = [(result, array), *args[1:]]
            else:
                new_args = [(result, array)]
            result = func(*new_args, **kw)
        else:
            if args[1:]:
                new_args = [(result, arrays[-1]), *args[1:]]
            else:
                new_args = [(result, arrays[-1])]

            return func(*new_args, **kw)

    _decorator.undecorated = func

    return _decorator

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.