Объединение двух одномерных массивов NumPy

266

У меня есть два простых одномерных массива в NumPy . Я должен быть в состоянии объединить их, используя numpy.concatenate . Но я получаю эту ошибку для кода ниже:

TypeError: только массивы длины 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. (Если вы хотите сложить их по глубине, например, в третьем измерении, используйте np.dstack). Обратите внимание, что последние похожи на пандpd.concat
smci

Ответы:

372

Строка должна быть:

numpy.concatenate([a,b])

Массивы, которые вы хотите объединить, должны передаваться как последовательность, а не как отдельные аргументы.

Из документации NumPy :

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

Соедините последовательность массивов вместе.

Он пытался интерпретировать ваш параметр bкак ось, поэтому он жаловался, что не может преобразовать его в скаляр.

Уинстон Эверт
источник
1
Спасибо! просто любопытно - какая логика стоит за этим?
user391339
8
@ user391339, что если вы хотите объединить три массива? Функция более полезна для получения последовательности, чем если бы она заняла два массива.
Уинстон Эверт
@WinstonEwert Если предположить, что проблема не в том, что он жестко запрограммирован на два аргумента, вы можете использовать его как numpy.concatenate(a1, a2, a3)или, numpy.concatenate(*[a1, a2, a3])если хотите. Python достаточно гибок, чтобы в конечном итоге разница выглядела скорее косметической, чем существенной, но это хорошо, когда API согласован (например, если все простые функции, которые принимают списки аргументов переменной длины, требуют явных последовательностей).
Джим К.
@JimK. Что будет с параметром оси?
Уинстон Эверт
1
Предполагая, что все объекты для объединения являются позиционными параметрами, вы можете оставить ось в качестве ключевого аргумента, например def concatx(*sequences, **kwargs)). Это не идеально, так как вы не можете назвать ключевые слова args явно в подписи таким образом, но есть обходные пути.
Джим К.
37

Существует несколько возможностей объединения 1D-массивов, например:

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

Все эти параметры одинаково быстры для больших массивов; для маленьких concatenateимеет небольшое преимущество:

введите описание изображения здесь

Сюжет создан с перфплотом :

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.
Ханнес Оврен
2
Вы правы - я был неправ. Я исправил свой исходный код, а также результат.
Семжон Мессингер,
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])
kmario23
источник
0

Еще несколько фактов из NumPy документов :

С синтаксисом как numpy.concatenate((a1, a2, ...), axis=0, out=None)

ось = 0 для послойной конкатенации

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

Я надеюсь, что это помогает !

Пе Дро
источник