Łączenie dwóch jednowymiarowych tablic NumPy

266

Mam dwie proste jednowymiarowe tablice w NumPy . Powinienem być w stanie połączyć je przy użyciu numpy.concatenate . Ale pojawia się ten błąd dla poniższego kodu:

TypeError: tylko tablice długości 1 mogą być konwertowane na skalary Pythona

Kod

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

Czemu?

wysoka przepustowość
źródło
Jeśli chcesz je połączyć (w jedną tablicę) wzdłuż osi, użyj np.concatenat(..., axis). Jeśli chcesz ułożyć je pionowo, użyj np.vstack. Jeśli chcesz ułożyć je w stosy (w wiele tablic) poziomo, użyj np.hstack. (Jeśli chcesz ułożyć je głęboko, tj. 3. wymiar, użyj np.dstack). Pamiętaj, że te ostatnie są podobne do pandpd.concat
smci

Odpowiedzi:

372

Linia powinna być:

numpy.concatenate([a,b])

Tablice, które chcesz połączyć, muszą być przekazywane jako sekwencja, a nie jako osobne argumenty.

Z dokumentacji NumPy :

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

Połącz sekwencję tablic razem.

Próbował zinterpretować twój bparametr parametru osi, dlatego narzekał, że nie może go przekonwertować na skalar.

Winston Ewert
źródło
1
dzięki! po prostu ciekawy - jaka jest tego logika?
user391339,
8
@ user391339, co jeśli chcesz połączyć trzy tablice? Ta funkcja jest bardziej przydatna w wykonywaniu sekwencji, jeśli zajmuje tylko dwie tablice.
Winston Ewert,
@WinstonEwert Zakładając, że problem nie polega na tym, że jest zakotwiczony w dwóch argumentach, możesz go użyć jak numpy.concatenate(a1, a2, a3)lub numpy.concatenate(*[a1, a2, a3])jeśli wolisz. Płynność Pythona jest na tyle duża, że ​​różnica wydaje się bardziej kosmetyczna niż istotna, ale dobrze jest, gdy API jest spójny (np. Jeśli wszystkie funkcje numpy, które pobierają listy argumentów o zmiennej długości, wymagają wyraźnych sekwencji).
Jim K.
@JimK. Co stałoby się z parametrem osi?
Winston Ewert
1
Zakładając, że rzeczami, które należy połączyć, są wszystkie parametry pozycyjne, możesz zachować oś jako argument słowa kluczowego np def concatx(*sequences, **kwargs).). Nie jest to idealne rozwiązanie, ponieważ wydaje się, że w ten sposób nie można wyraźnie nazwać argumentów argumentami w podpisie, ale istnieją obejścia.
Jim K.
37

Istnieje kilka możliwości łączenia tablic 1D, np.

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

Wszystkie te opcje są równie szybkie w przypadku dużych tablic; dla małych concatenatema niewielką krawędź:

wprowadź opis zdjęcia tutaj

Fabuła została stworzona za pomocą 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)",
)
Nico Schlömer
źródło
9
Wszystkie alternatywy wykorzystują np.concatenate. Po prostu ręcznie masują listę wejściową na różne sposoby. np.stackna przykład dodaje dodatkowy wymiar do wszystkich tablic wejściowych. Spójrz na ich kod źródłowy. Tylko concatenatejest kompilowany.
hpaulj
1
Wystarczy dodać do komentarza @hpaulj - czasy zbiegają się w miarę wzrostu rozmiarów tablic, ponieważ np.concatenatetworzy kopie danych wejściowych. Ta pamięć i koszt czasu przewyższają czas spędzony na „masowaniu” danych wejściowych.
n1k31t4
31

Pierwszym parametrem concatenatepowinna być sama sekwencja tablic do konkatenacji:

numpy.concatenate((a,b)) # Note the extra parentheses.
Gabe
źródło
10

Alternatywą jest użycie krótkiej formy „konkatenatu”, czyli „r _ [...]” lub „c _ [...]”, jak pokazano w przykładowym kodzie poniżej (patrz http://wiki.scipy.org / NumPy_for_Matlab_Users, aby uzyskać dodatkowe informacje):

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

Co skutkuje w:

[ 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.]]
Semjon Mössinger
źródło
2
vector_b = [1,1,1,1] #short form of "array", to po prostu nieprawda. vector_b będzie standardowym typem listy Pythona. Numpy jest jednak całkiem dobry w akceptowaniu sekwencji zamiast zmuszania wszystkich danych wejściowych do typów numpy.array.
Hannes Ovrén
2
Masz rację - myliłem się. Poprawiłem kod źródłowy oraz wynik.
Semjon Mössinger
0

Oto kilka podejść do zrobienia tego przy użyciu numpy.ravel(), numpy.array()wykorzystując fakt, że tablice 1D można rozpakować w zwykłe elementy:

# 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
źródło
0

Kilka innych faktów z niezliczonych dokumentów :

Ze składnią jako numpy.concatenate((a1, a2, ...), axis=0, out=None)

oś = 0 dla konkatenacji wierszowej oś = 1 dla konkatenacji kolumnowej

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

Mam nadzieję, że to pomoże !

Pe Dro
źródło