Concatenazione di due matrici NumPy unidimensionali


266

Ho due semplici matrici unidimensionali in NumPy . Dovrei essere in grado di concatenarli usando numpy.concatenate . Ma ottengo questo errore per il codice seguente:

TypeError: solo le matrici di lunghezza 1 possono essere convertite in scalari Python

Codice

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

Perché?


Se si desidera concatenarli (in un singolo array) lungo un asse, utilizzare np.concatenat(..., axis). Se si desidera impilarli verticalmente, utilizzare np.vstack. Se si desidera impilarli orizzontalmente (in più array), utilizzare np.hstack. (Se si desidera impilarli in profondità, vale a dire la 3a dimensione, utilizzare np.dstack). Si noti che questi ultimi sono simili ai pandapd.concat
smci

Risposte:


372

La linea dovrebbe essere:

numpy.concatenate([a,b])

Le matrici che si desidera concatenare devono essere passate come sequenza, non come argomenti separati.

Dalla documentazione di NumPy :

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

Unire una sequenza di matrici insieme.

Stava cercando di interpretare il tuo bcome parametro dell'asse, motivo per cui si lamentava di non poterlo convertire in uno scalare.


1
Grazie! solo curioso - qual è la logica dietro questo?
user391339,

8
@ user391339, cosa succede se si desidera concatenare tre array? La funzione è più utile nel prendere una sequenza se poi ha preso solo due matrici.
Winston Ewert,

@WinstonEwert Supponendo che il problema non sia che sia codificato su due argomenti, potresti usarlo come numpy.concatenate(a1, a2, a3)o numpy.concatenate(*[a1, a2, a3])se preferisci. Python è abbastanza fluido da far sembrare la differenza più estetica che sostanziale, ma è buona quando l'API è coerente (ad esempio se tutte le funzioni intorpidite che accettano elenchi di argomenti a lunghezza variabile richiedono sequenze esplicite).
Jim K.

@JimK. Cosa accadrebbe al parametro axis?
Winston Ewert,

1
Supponendo che le cose da concatenare siano tutti parametri posizionali, è possibile mantenere l'asse come argomento di una parola chiave, ad esempio def concatx(*sequences, **kwargs). Non è l'ideale poiché non riesci a nominare la parola chiave arg esplicitamente nella firma in questo modo, ma ci sono soluzioni alternative.
Jim K.

37

Esistono diverse possibilità per concatenare gli array 1D, ad es.

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

Tutte queste opzioni sono ugualmente veloci per array di grandi dimensioni; per i più piccoli, concatenateha un leggero vantaggio:

inserisci qui la descrizione dell'immagine

La trama è stata creata con 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
Le alternative tutte usano np.concatenate. Hanno appena massaggiato l'elenco di input in vari modi prima della mano. np.stackad esempio aggiunge una dimensione aggiuntiva a tutti gli array di input. Guarda il loro codice sorgente. Solo concatenateè compilato.
hpaulj,

1
Solo per aggiungere al commento di @hpaulj: i tempi convergono quando la dimensione delle matrici aumenta perché le np.concatenatecopie degli input vengono fatte. Questo costo di memoria e tempo supera quindi il tempo impiegato a "massaggiare" l'input.
n1k31t4

31

Il primo parametro concatenatedovrebbe essere esso stesso una sequenza di matrici per concatenare:

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

10

Un'alternativa è usare la forma abbreviata di "concatenare" che è "r _ [...]" o "c _ [...]" come mostrato nel codice di esempio sotto (vedi http://wiki.scipy.org / NumPy_for_Matlab_Users per ulteriori informazioni):

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

Che si traduce in:

[ 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", Questo semplicemente non è vero. vector_b sarà un tipo di elenco Python standard. Numpy è comunque abbastanza bravo ad accettare sequenze invece di forzare tutti gli input ad essere tipi numpy.array.
Hannes Ovrén,

2
Hai ragione - ho sbagliato. Ho corretto il mio codice sorgente e il risultato.
Semjon Mössinger,

0

Ecco altri approcci per farlo utilizzando numpy.ravel(), numpy.array()utilizzando il fatto che gli array 1D possono essere decompressi in elementi semplici:

# 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

Alcuni altri fatti dai documenti intorpiditi :

Con sintassi come numpy.concatenate((a1, a2, ...), axis=0, out=None)

asse = 0 per la concatenazione per riga asse = 1 per la concatenazione per colonna

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

Spero possa essere d'aiuto !

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.