Numpy: aggiunge una riga all'array


161

Come si aggiungono le righe a una matrice numpy?

Ho un array A:

A = array([[0, 1, 2], [0, 2, 0]])

Vorrei aggiungere righe a questo array da un altro array X se il primo elemento di ogni riga in X soddisfa una condizione specifica.

Le matrici Numpy non hanno un metodo "append" come quello delle liste, o almeno così sembra.

Se A e X fossero liste farei semplicemente:

for i in X:
    if i[0] < 3:
        A.append(i)

C'è un modo numpythonic per fare l'equivalente?

Grazie, S ;-)


Risposte:


120

Che cosa è X? Se si tratta di un array 2D, come è possibile quindi confrontare la sua riga con un numero i < 3:?

MODIFICA dopo il commento di OP:

A = array([[0, 1, 2], [0, 2, 0]])
X = array([[0, 1, 2], [1, 2, 0], [2, 1, 2], [3, 2, 0]])

aggiungi a Atutte le righe da Xcui il primo elemento < 3:

import numpy as np
A = np.vstack((A, X[X[:,0] < 3]))

# returns: 
array([[0, 1, 2],
       [0, 2, 0],
       [0, 1, 2],
       [1, 2, 0],
       [2, 1, 2]])

1
Scusate buon punto! Assumi un array 2D di cui il primo elemento di ogni riga deve soddisfare una condizione. Lo modificherò. Grazie, S ;-)
Darren J. Fitzpatrick,

2
@ DarrenJ.Fitzpatrick Tieni presente che facendo questo tipo di manipolazione lavori contro il buon lavoro che Numpy svolge nella pre-allocazione della memoria per l'array esistente A. Chiaramente per piccoli problemi come in questa risposta questo non è un problema, ma può essere più problematico per i dati di grandi dimensioni.
dtlussier,

166

bene puoi farlo:

  newrow = [1,2,3]
  A = numpy.vstack([A, newrow])

2
@Kris Perché è deprecato? Non vedo nulla nei documenti
Georgy,

1
@Georgy Ad essere sincero, non lo so. Ero qui alla ricerca di risposte uguali a te :-). Non ricordo ora perché ho scritto sopra il commento. Devo aver visto nei documenti che è deprecato. Ma guardando i documenti ora ... non lo dice. È possibile che lo abbiano deprecato, poi abbiano cambiato idea e abbiano deciso che sarebbe troppo fastidioso per troppe persone deprecarlo e rimuoverlo?
Kris,

32

Poiché questa domanda è stata posta 7 anni prima, nell'ultima versione che sto usando è la versione numpy 1.13 e python3, sto facendo la stessa cosa con l'aggiunta di una riga a una matrice, ricordati di mettere una doppia parentesi nel secondo argomento, in caso contrario, genererà un errore di dimensione.

Qui sto aggiungendo sulla matrice A

1 2 3
4 5 6

con una riga

7 8 9

stesso utilizzo in np.r_

A= [[1, 2, 3], [4, 5, 6]]
np.append(A, [[7, 8, 9]], axis=0)

    >> array([[1, 2, 3],
              [4, 5, 6],
              [7, 8, 9]])
#or 
np.r_[A,[[7,8,9]]]

Solo per l'interesse di qualcuno, se desideri aggiungere una colonna,

array = np.c_[A,np.zeros(#A's row size)]

seguendo quello che abbiamo fatto prima sulla matrice A, aggiungendo una colonna ad essa

np.c_[A, [2,8]]

>> array([[1, 2, 3, 2],
          [4, 5, 6, 8]])

11

Se non sono necessari calcoli dopo ogni riga, è molto più veloce aggiungere righe in Python, quindi convertirle in numpy. Ecco i test di temporizzazione usando python 3.6 contro numpy 1.14, aggiungendo 100 righe, una alla volta:

import numpy as np 
from time import perf_counter, sleep

def time_it():
    # Compare performance of two methods for adding rows to numpy array
    py_array = [[0, 1, 2], [0, 2, 0]]
    py_row = [4, 5, 6]
    numpy_array = np.array(py_array)
    numpy_row = np.array([4,5,6])
    n_loops = 100

    start_clock = perf_counter()
    for count in range(0, n_loops):
       numpy_array = np.vstack([numpy_array, numpy_row]) # 5.8 micros
    duration = perf_counter() - start_clock
    print('numpy 1.14 takes {:.3f} micros per row'.format(duration * 1e6 / n_loops))

    start_clock = perf_counter()
    for count in range(0, n_loops):
        py_array.append(py_row) # .15 micros
    numpy_array = np.array(py_array) # 43.9 micros       
    duration = perf_counter() - start_clock
    print('python 3.6 takes {:.3f} micros per row'.format(duration * 1e6 / n_loops))
    sleep(15)

#time_it() prints:

numpy 1.14 takes 5.971 micros per row
python 3.6 takes 0.694 micros per row

Quindi, la semplice soluzione alla domanda originale, di sette anni fa, è usare vstack () per aggiungere una nuova riga dopo aver convertito la riga in un array numpy. Ma una soluzione più realistica dovrebbe considerare le scarse prestazioni di vstack in tali circostanze. Se non è necessario eseguire l'analisi dei dati sull'array dopo ogni aggiunta, è meglio bufferizzare le nuove righe in un elenco di righe Python (un elenco di elenchi, in realtà) e aggiungerle come gruppo all'array numpy usando vstack () prima di fare qualsiasi analisi dei dati.


10

Puoi anche fare questo:

newrow = [1,2,3]
A = numpy.concatenate((A,newrow))

2
hmmm. quando l'ho provato, è stato aggiunto alla fine di A, anziché aggiungere una nuova riga come richiesto da OP.
Todd Curry,

13
probabilmentenp.concatenate((A,newrow), axis=0)
Konstantinos Roditakis l'

3
A partire dalla versione numpy 1.12.1(e in Python 3), sembra come tentare di concatenare un vettore a una matrice che si alza ValueError: all the input arrays must have same number of dimensions. Sembra che desideri che il vettore venga rimodellato esplicitamente in un vettore colonna o riga prima che sia disposto a concatenarlo.
MRule

3
@MRule si può risolvere che utilizzando doppie parentesi quadre come per la risposta da @Flora PJ Li stackoverflow.com/a/47845065/1410035 . newrow = [[1,2,3]]
Tom Saleeba

5
import numpy as np
array_ = np.array([[1,2,3]])
add_row = np.array([[4,5,6]])

array_ = np.concatenate((array_, add_row), axis=0)

3

Se riesci a fare la costruzione in una sola operazione, allora qualcosa come la risposta di indicizzazione vstack con fantasia è un approccio eccellente. Ma se le tue condizioni sono più complicate o le tue righe arrivano al volo, potresti voler espandere l'array. In effetti il ​​modo numpythonic di fare qualcosa del genere - far crescere dinamicamente un array - è far crescere un elenco in modo dinamico:

A = np.array([[1,2,3],[4,5,6]])
Alist = [r for r in A]
for i in range(100):
    newrow = np.arange(3)+i
    if i%5:
        Alist.append(newrow)
A = np.array(Alist)
del Alist

Le liste sono altamente ottimizzate per questo tipo di schema di accesso; non hai una comoda indicizzazione multidimensionale numpy mentre sei in forma di elenco, ma finché stai accodando è difficile fare meglio di un elenco di array di righe.


3

Uso "np.vstack" che è più veloce, EX:

import numpy as np

input_array=np.array([1,2,3])
new_row= np.array([4,5,6])

new_array=np.vstack([input_array, new_row])

2

È possibile utilizzare numpy.append()per aggiungere una riga all'array intorpidito e rimodellare in seguito una matrice.

import numpy as np
a = np.array([1,2])
a = np.append(a, [3,4])
print a
# [1,2,3,4]
# in your example
A = [1,2]
for row in X:
    A = np.append(A, row)
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.