Łą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?


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.


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)",
)

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.

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

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

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 !

Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.