English | 简体中文 | 繁體中文 | Русский язык | Français | Español | Português | Deutsch | 日本語 | 한국어 | Italiano | بالعربية

Iterazione degli array NumPy

L'oggetto iteratore NumPy numpy.nditer offre un modo flessibile per accedere a un singolo o più elementi di un array.

Il compito più fondamentale dell'iteratore è quello di accedere agli elementi dell'array.

Utilizzeremo la funzione arange() per creare un array 2x3 e iterarlo utilizzando nditer.

import numpy as np
a = np.arange(12).reshape(2,6)
print('L'array originale è:')
print(a)
print('\n')
print(('Elemento iterativo: '))
for	x	in	np.nditer(a):
    print(x, end=" ")

Risultato di output:

L'array originale è il seguente:
[	0	1	2	3	4	5]
 [	6	7	8	9	10	11]
Esegui l'output iterativo degli elementi dell'array come segue:
0 1 2 3 4 5 6 7 8 9 10 11

L'esempio sopra non utilizza l'ordine standard C o Fortran, l'ordine scelto è coerente con la disposizione della memoria dell'array, il che migliora l'efficienza dell'accesso, per default è l'ordine di predominio delle righe (row-major order, o C-order).

Questo riflette il fatto che in condizioni di default è sufficiente accedere a ciascun elemento senza dover considerare il suo ordine specifico. Possiamo vedere questo iterando sull'array di trasposizione sopra menzionato e facendo un confronto con il modo di accedere alla copia della trasposizione dell'array con ordine C, come nell'esempio seguente:

import numpy as np
a = np.arange(12).reshape(2,6)
per x in np.nditer(a.T):
    print(x, end=" ")
print('\n')
per x in np.nditer(a.T.copy(order='C')):
    print(x, end=" ")

Risultato di output:

0 1 2 3 4 5 6 7 8 9 10 11 
0 6 1 7 2 8 3 9 4 10 5 11

dal caso specifico sopra riportato si può notare che l'ordine di scansione di a e a.T è lo stesso, ossia che l'ordine di archiviazione in memoria è anche lo stesso, ma a.T.copy(order = 'C') i risultati della scansione sono diversi, poiché il suo modo di archiviazione non è lo stesso degli altri due, per default è l'accesso per riga.

controllo dell'ordine di scansione

per x in np.nditer(a, order='F'):Fortran order, è il predominio dell'ordine delle colonne;per x in np.nditer(a.T, order='C'):C order, è il predominio dell'ordine delle righe;

import numpy as np
a = np.arange(0,100,5)
a = a.reshape(4,5)
print('L'array originale è:')
print(a)
print('\n')
print('la trasposizione dell'array originale è:');
b = a.T
print(b)
print('\n')
print('in ordine di stile C:');
c = b.copy(order='C')
print(c)
per x in np.nditer(c):
    print(x, end=" ")
print('\n')
print('in ordine di stile F:');
c = b.copy(order='F')
print(c)
per x in np.nditer(c):
    print(x, end=" ")

Risultato di output:

L'array originale è:
[[0 5 10 15 20]
 [25 30 35 40 45]
 [50 55 60 65 70]
 [75 80 85 90 95]
la trasposizione dell'array originale è:
[[0 25 50 75]
 [5 30 55 80]
 [10 35 60 85]
 [15 40 65 90]
 [20 45 70 95]
Ordinato in stile C:
[[0 25 50 75]
 [5 30 55 80]
 [10 35 60 85]
 [15 40 65 90]
 [20 45 70 95]
0 25 50 75 5 30 55 80 10 35 60 85 15 40 65 90 20 45 70 95 
Ordinato in stile F:
[[0 25 50 75]
 [5 30 55 80]
 [10 35 60 85]
 [15 40 65 90]
 [20 45 70 95]
0 5 10 15 20 25 30 35 40 45 50 55 60 65 70 75 80 85 90 95

è possibile impostare esplicitamente per costringere l'oggetto nditer ad utilizzare un certo ordine:

import numpy as np
a = np.arange(0,100,5)
a = a.reshape(4,5)
print('L'array originale è:')
print(a)
print('\n')
print('in ordine di stile C:');
per x in np.nditer(a, order = 'C'):
    print(x, end=", ");
print('\n')
print('in ordine di stile F:');
per x in np.nditer(a, order = 'F'):
    print(x, end=" ")

Risultato di output:

L'array originale è:
[[0 5 10 15 20]
 [25 30 35 40 45]
 [50 55 60 65 70]
 [75 80 85 90 95]
Ordinato in stile C:
0, 5, 10, 15, 20, 25, 30, 35, 40, 45, 50, 55, 60, 65, 70, 75, 80, 85, 90, 95, 
Ordinato in stile F:
0 25 50 75 5 30 55 80 10 35 60 85 15 40 65 90 20 45 70 95

Modificare i valori degli elementi dell'array

L'oggetto nditer ha un altro parametro op_flags opzionale. Di default, nditer considera l'array da iterare come un oggetto solo-lettura (read-only). Per modificare i valori degli elementi dell'array durante la scansione, è necessario specificare il modello read-write o write-only.

import numpy as np
a = np.arange(0,100,5)
a = a.reshape(4,5)
print('L'array originale è:')
print(a)
print('\n')
for x in np.nditer(a, op_flags=['readwrite']):
    x[...]=2*x
print('L'array modificato è:')
print(a)

Risultato di output:

L'array originale è:
[[0 5 10 15 20]
 [25 30 35 40 45]
 [50 55 60 65 70]
 [75 80 85 90 95]
L'array modificato è:
[[0 10 20 30 40]
 [0 10 20 30 40]
 [100 110 120 130 140]
 [150 160 170 180 190]

Usare il ciclo esterno

Il costruttore della classe nditer ha un parametro flags, che può accettare i seguenti valori:

ParametroDescrizione
c_indexPuò tracciare l'indice in ordine C
f_indexPuò tracciare l'indice in ordine Fortran
multi-indexOgni iterazione può tracciare un tipo di indice
external_loopI valori forniti sono array uno-dimensionali con più valori, non array zero-dimensionali

Nell'esempio seguente, l'iteratore esplora corrispondenti a ciascuna colonna e li combina in un array uno-dimensionale.

import numpy as np
a = np.arange(0,100,5)
a = a.reshape(4,5)
print('L'array originale è:')
print(a)
print('\n')
print('L'array modificato è:')
for x in np.nditer(a, flags=['external_loop'], order='F'):
    print(x, end=" ")

Risultato di output:

L'array originale è:
[[0 5 10 15 20]
 [25 30 35 40 45]
 [50 55 60 65 70]
 [75 80 85 90 95]
L'array modificato è:
[0 25 50 75] [5 30 55 80] [10 35 60 85] [15 40 65 90] [20 45 70 95]

Iterazione di broadcasting

Se due array sono broadcastabili, l'oggetto combinato nditer può iterarli contemporaneamente. Supponiamo che l'array a abbia dimensioni 3x4 e l'array b abbia dimensioni 1x4, allora si utilizza il seguente iteratore (l'array b viene broadcastato alla dimensione di a).

import numpy as np
a = np.arange(0, 60, 5)
a = a.reshape(3, 4)
print('Il primo array è:')
print(a)
print('\n')
print('Il secondo array è:')
b = np.array([1, 2, 3, 4], dtype=int)
print(b)
print('\n')
print('L'array modificato è:')
for x, y in np.nditer([a, b]):
    print("%d:%d" % (x, y), end=" ")

Risultato di output:

Il primo array è:
[[ 0 5 10 15]
 [20 25 30 35]
 [40 45 50 55]]
Il secondo array è:
[1 2 3 4]
L'array modificato è:
0:1, 5:2, 10:3, 15:4, 20:1, 25:2, 30:3, 35:4, 40:1, 45:2, 50:3, 55:4,