Risposte:
>>> test[:,0]
array([1, 3, 5])
Allo stesso modo,
>>> test[1,:]
array([3, 4])
ti consente di accedere alle righe. Questo è trattato nella Sezione 1.4 (Indicizzazione) del riferimento NumPy . Questo è veloce, almeno nella mia esperienza. È certamente molto più veloce dell'accesso a ciascun elemento in un ciclo.
E se si desidera accedere a più di una colonna alla volta, è possibile:
>>> test = np.arange(9).reshape((3,3))
>>> test
array([[0, 1, 2],
[3, 4, 5],
[6, 7, 8]])
>>> test[:,[0,2]]
array([[0, 2],
[3, 5],
[6, 8]])
test[:,[0,2]]
semplicemente accede ai dati, ad esempio, test[:, [0,2]] = something
modifica il test e non crea un altro array. Ma copy_test = test[:, [0,2]]
in effetti crea una copia come dici tu.
test[:,[0,2]]
accede semplicemente ai dati mentre test[:, [0, 2]][:, [0, 1]]
no? Sembra poco intuitivo che fare di nuovo la stessa cosa abbia un risultato diverso.
>>> test[:,0]
array([1, 3, 5])
questo comando ti dà un vettore di riga, se vuoi solo passare su di esso, va bene, ma se vuoi hstack con qualche altro array con dimensione 3xN, avrai
ValueError: all the input arrays must have same number of dimensions
mentre
>>> test[:,[0]]
array([[1],
[3],
[5]])
ti dà un vettore di colonna, in modo da poter eseguire operazioni concatenate o hstack.
per esempio
>>> np.hstack((test, test[:,[0]]))
array([[1, 2, 1],
[3, 4, 3],
[5, 6, 5]])
È inoltre possibile trasporre e restituire una riga:
In [4]: test.T[0]
Out[4]: array([1, 3, 5])
Per ottenere diverse colonne indipendenti, basta:
> test[:,[0,2]]
otterrai colonne 0 e 2
Sebbene alla domanda sia stata data una risposta, vorrei menzionare alcune sfumature.
Supponiamo che tu sia interessato alla prima colonna dell'array
arr = numpy.array([[1, 2],
[3, 4],
[5, 6]])
Come già sapete da altre risposte, per ottenerlo sotto forma di "vettore riga" (matrice di forme (3,)
), usate l'affettamento:
arr_c1_ref = arr[:, 1] # creates a reference to the 1st column of the arr
arr_c1_copy = arr[:, 1].copy() # creates a copy of the 1st column of the arr
Per verificare se un array è una vista o una copia di un altro array è possibile effettuare le seguenti operazioni:
arr_c1_ref.base is arr # True
arr_c1_copy.base is arr # False
vedi ndarray.base .
Oltre all'ovvia differenza tra i due (la modifica arr_c1_ref
influirà arr
), il numero di byte-passi per attraversarli è diverso:
arr_c1_ref.strides[0] # 8 bytes
arr_c1_copy.strides[0] # 4 bytes
vedere i passi . Perché questo è importante? Immagina di avere un array molto grande al A
posto di arr
:
A = np.random.randint(2, size=(10000,10000), dtype='int32')
A_c1_ref = A[:, 1]
A_c1_copy = A[:, 1].copy()
e vuoi calcolare la somma di tutti gli elementi della prima colonna, ovvero A_c1_ref.sum()
o A_c1_copy.sum()
. L'uso della versione copiata è molto più veloce:
%timeit A_c1_ref.sum() # ~248 µs
%timeit A_c1_copy.sum() # ~12.8 µs
Ciò è dovuto al diverso numero di passi menzionati prima:
A_c1_ref.strides[0] # 40000 bytes
A_c1_copy.strides[0] # 4 bytes
Anche se potrebbe sembrare che l'uso delle copie delle colonne sia migliore, non è sempre vero per il fatto che fare una copia richiede tempo e utilizza più memoria (in questo caso mi ci sono voluti circa 200 µs per creare il A_c1_copy
). Tuttavia, se abbiamo bisogno della copia in primo luogo, o dobbiamo fare molte operazioni diverse su una colonna specifica dell'array e siamo d'accordo con il sacrificare memoria per la velocità, quindi fare una copia è la strada da percorrere.
Nel caso in cui siamo interessati a lavorare principalmente con le colonne, potrebbe essere una buona idea creare il nostro array in ordine di colonna maggiore ('F') anziché nell'ordine di riga maggiore ('C') (che è l'impostazione predefinita ), quindi esegui lo slicing come prima per ottenere una colonna senza copiarla:
A = np.asfortranarray(A) # or np.array(A, order='F')
A_c1_ref = A[:, 1]
A_c1_ref.strides[0] # 4 bytes
%timeit A_c1_ref.sum() # ~12.6 µs vs ~248 µs
Ora, eseguire l'operazione di somma (o qualsiasi altra) su una vista a colonne è molto più veloce.
Vorrei infine notare che trasporre un array e usare il taglio di riga è lo stesso che usare il taglio di colonna sull'array originale, perché il recepimento avviene semplicemente scambiando la forma e i passi dell'array originale.
A.T[1,:].strides[0] # 40000