Reputation: 13771
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!
Upvotes: 26
Views: 77741
Reputation: 56
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
Upvotes: 0
Reputation: 1
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]])
Upvotes: 0
Reputation: 11
You can simply use numpy
's hstack
function.
e.g.
import numpy as np
combined = np.hstack((array1,array2))
Upvotes: 0
Reputation: 215117
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]])
Upvotes: 34