Об’єднання двох одновимірних масивів NumPy


266

У мене є два простих одновимірних масиви в NumPy . Я повинен мати можливість об'єднати їх за допомогою numpy.concatenate . Але я отримую цю помилку для коду нижче:

TypeError: до скаторів Python можна перетворити лише масиви довжиною-1

Код

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
Дякую! просто цікаво - в чому полягає логіка цього?
користувач391339

8
@ user391339, що робити, якщо ви хочете об'єднати три масиви? Ця функція корисніша при прийнятті послідовності, якщо вона просто взяла два масиви.
Вінстон Еверт

@WinstonEwert Якщо припустити, що проблема полягає не в тому, що вона кодується двома аргументами, ви можете використовувати її як, numpy.concatenate(a1, a2, a3)або numpy.concatenate(*[a1, a2, a3])якщо хочете. Жидкості Python достатньо, щоб різниця виявилася більш косметичною, ніж істотною, але це добре, коли API є послідовним (наприклад, якщо всі функції numpy, які приймають аргументи змінної довжини, вимагають явних послідовностей).
Джим К.

@JimK. Що буде з параметром осі?
Вінстон Еверт

1
Якщо припустити, що об'єднуються всі параметри позиції, ви можете зберегти вісь як аргумент ключового слова, наприклад def concatx(*sequences, **kwargs)). Це не ідеально, оскільки ви не можете, таким чином, підписувати ключові аргументи явно в підписі таким чином, але є обхідні шляхи.
Джим К.

37

Існує кілька можливостей для об'єднання 1D масивів, наприклад,

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

Усі ці варіанти однаково швидкі для великих масивів; для маленьких concatenateмає невеликий край:

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

Сюжет створений за допомогою 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)",
)

9
Альтернативи всі використовують np.concatenate. Вони просто масажують вхідний список різними способами перед рукою. np.stackнаприклад додає додатковий вимір для всіх вхідних масивів. Подивіться на їх вихідний код. Тільки concatenateскладено.
hpaulj

1
Просто для допису до коментаря @hpaulj - час усе збігається, коли розмір масивів збільшується, оскільки np.concatenateробить копії входів. Ця пам'ять і вартість часу переважають за час, витрачений на «масаж» введення.
n1k31t4

31

Перший параметр to 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.
Hannes Ovrén

2
Ви маєте рацію - я помилився. Я виправив свій вихідний код, а також результат.
Semjon Mössinger

0

Ось більше підходів для цього, використовуючи numpy.ravel(), numpy.array()використовуючи той факт, що 1D масиви можна розпакувати на прості елементи:

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

0

Ще кілька фактів з nummy docs :

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

ось = 0 для вікон об'єднання в рядку = 1 для об'єднання в стовпці

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

Я сподіваюся, що це допомагає!

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.