Verkettung von zwei eindimensionalen NumPy-Arrays


266

Ich habe zwei einfache eindimensionale Arrays in NumPy . Ich sollte in der Lage sein, sie mit numpy.concatenate zu verketten . Aber ich bekomme diesen Fehler für den folgenden Code:

TypeError: Nur Arrays der Länge 1 können in Python-Skalare konvertiert werden

Code

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

Warum?


Wenn Sie sie (zu einem einzelnen Array) entlang einer Achse verketten möchten , verwenden Sie np.concatenat(..., axis). Wenn Sie sie vertikal stapeln möchten, verwenden Sie np.vstack. Wenn Sie sie horizontal (in mehrere Arrays) stapeln möchten, verwenden Sie np.hstack. (Wenn Sie sie in der Tiefe stapeln möchten, dh in der 3. Dimension, verwenden Sie np.dstack). Beachten Sie, dass letztere Pandas ähnlich sindpd.concat
smci

Antworten:


372

Die Zeile sollte sein:

numpy.concatenate([a,b])

Die Arrays, die Sie verketten möchten, müssen als Sequenz und nicht als separate Argumente übergeben werden.

Aus der NumPy-Dokumentation :

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

Verbinden Sie eine Folge von Arrays.

Es wurde versucht, Ihren bals Achsenparameter zu interpretieren , weshalb es sich beschwerte, dass es nicht in einen Skalar konvertiert werden konnte.


1
Vielen Dank! nur neugierig - was ist die Logik dahinter?
user391339

8
@ user391339, was ist, wenn Sie drei Arrays verketten möchten? Die Funktion ist beim Erstellen einer Sequenz nützlicher als wenn nur zwei Arrays benötigt werden.
Winston Ewert

@WinstonEwert Angenommen, das Problem besteht nicht darin, dass es auf zwei Argumente fest codiert ist, können Sie es wie numpy.concatenate(a1, a2, a3)oder numpy.concatenate(*[a1, a2, a3])wenn Sie es vorziehen, verwenden. Python ist so flüssig, dass sich der Unterschied eher kosmetisch als wesentlich anfühlt, aber es ist gut, wenn die API konsistent ist (z. B. wenn alle Numpy-Funktionen, die Argumentlisten mit variabler Länge verwenden, explizite Sequenzen erfordern).
Jim K.

@ JimK. Was würde mit dem Achsenparameter passieren?
Winston Ewert

1
Angenommen, die zu verkettenden Dinge sind alle Positionsparameter, könnten Sie die Achse als Schlüsselwortargument beibehalten (z def concatx(*sequences, **kwargs). B. ). Es ist nicht ideal, da Sie die Keyword-Argumente in der Signatur auf diese Weise nicht explizit benennen können, aber es gibt Problemumgehungen.
Jim K.

37

Es gibt verschiedene Möglichkeiten, 1D-Arrays zu verketten, z.

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

Alle diese Optionen sind für große Arrays gleich schnell. für kleine concatenatehat eine leichte Kante:

Geben Sie hier die Bildbeschreibung ein

Die Handlung wurde mit perfplot erstellt :

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
Die Alternativen nutzen alle np.concatenate. Sie massieren einfach die Eingabeliste auf verschiedene Arten vor der Hand. np.stackFügt beispielsweise allen Eingabearrays eine zusätzliche Dimension hinzu. Schauen Sie sich ihren Quellcode an. Nur concatenatewird kompiliert.
hpaulj

1
Nur um @hpauljs Kommentar zu ergänzen: Die Zeiten konvergieren alle mit zunehmender Größe der Arrays, da np.concatenateKopien der Eingaben erstellt werden. Diese Speicher- und Zeitkosten überwiegen dann die Zeit, die für das "Massieren" der Eingabe aufgewendet wurde.
n1k31t4

31

Der erste Parameter concatenatesollte selbst eine Folge von zu verkettenden Arrays sein :

numpy.concatenate((a,b)) # Note the extra parentheses.

10

Eine Alternative besteht darin, die Kurzform "verketten" zu verwenden, die entweder "r _ [...]" oder "c _ [...]" lautet, wie im folgenden Beispielcode gezeigt (siehe http://wiki.scipy.org) / NumPy_for_Matlab_Users für zusätzliche Informationen):

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

Was in ... endet:

[ 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", das ist einfach nicht wahr. vector_b ist ein Standard-Python-Listentyp. Numpy ist jedoch ziemlich gut darin, Sequenzen zu akzeptieren, anstatt alle Eingaben zu numpy.array-Typen zu zwingen.
Hannes Ovrén

2
Du hast recht - ich habe mich geirrt. Ich habe meinen Quellcode sowie das Ergebnis korrigiert.
Semjon Mössinger

0

Hier sind weitere Ansätze, dies zu tun , indem Sie numpy.ravel(), numpy.array(), unter Verwendung der Tatsache , dass 1D - Arrays in einfache Elemente ausgepackt werden können:

# 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

Einige weitere Fakten aus den numpy docs :

Mit Syntax als numpy.concatenate((a1, a2, ...), axis=0, out=None)

Achse = 0 für zeilenweise Verkettung Achse = 1 für spaltenweise Verkettung

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

Ich hoffe, es hilft !

Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.