NumPy supporta una varietà di tipi numerici maggiore rispetto a Python, perciò è importante comprendere appieno quali sono i tipi di dati e come vengono definiti, per poter lavorare al meglio con questa libreria.
In questa lezione vedremo quindi l’oggetto dtype alla base della definizione dei tipi di dati in NumPy e i principali tipi di dati definiti. Faremo alcuni semplici esempi pratici.
L’oggetto dtype
Un data type (dtype
) object, istanzanziato tramite la classe numpy.dtype
, definisce come devono essere interpretati i byte corrispondenti a un elemento dell'array. Descrive inoltre i seguenti aspetti dei dati.
Aspetto | Descrizione |
---|---|
tipi dei dati | come integer
float
Ci sono diversi tipi scalari forniti da NumPy, come numpy.int_
numpy.floatl_
dtype
|
la dimensione del dato | come il numero di byte di un float |
l’ordine dei byte | L'ordine dei byte viene deciso anteponendo <
>
|
il tipo di dato è structured
|
un tipo di dato creato dall’utente e che può includere array e dtypes
|
il tipo di dato è un sotto-array | può descrivere elementi che sono essi stessi matrici di elementi di un altro tipo di dati e che devono avere una dimensione fissa ed un tipo di dato specifico |
Un oggetto dtype
numpy.dtype()
dtype
int32
dt_int32 = np.dtype('int32')
o in modo equivalente utilizzando al posto della stringa 'int32'
np.int32
dt_int32 = np.dtype(np.int32)
stampando la variabile otterremo
dtype('int32')
Questa classe offre inoltre diversi attributi come ad esempio numpy.dtype.isbuiltin
dtype
Per esempio, per la nostra variabile dt_int32
dt_int32.isbuiltin
1
dove il valore 1
dtype
documentazione ufficiale
I Tipi
Come anticipato all’inizio di questa lezione, NumPy supporta una varietà maggiore di tipi numerici rispetto a Python. Di seguito è riportata una semplice tabella riassuntiva che mostra il parallelo tra i tipi di dati in NumPy e quelli in C
Tipo di dato in NumPy | Tipo di dato in C | Descrizione |
---|---|---|
numpy.bool_
|
bool
|
Valore booleano (True|False
byte
|
numpy.byte
|
signed char
|
definito dalla piattaforma |
numpy.ubyte
|
unsigned char
|
definito dalla piattaforma |
numpy.short
|
short
|
definito dalla piattaforma |
numpy.ushort
|
unsigned short
|
definito dalla piattaforma |
numpy.intc
|
int
|
definito dalla piattaforma |
numpy.uintc
|
unsigned int
|
definito dalla piattaforma |
numpy.int_
|
long
|
definito dalla piattaforma |
numpy.uint
|
unsigned long
|
definito dalla piattaforma |
numpy.longlong
|
long long
|
definito dalla piattaforma |
numpy.ulonglong
|
unsigned long long
|
definito dalla piattaforma |
numpy.half / numpy.float16
|
- | float a metà della precisione |
numpy.single
|
float
|
definito dalla piattaforma |
numpy.double
|
double
|
definito dalla piattaforma |
numpy.longdouble
|
long double
|
definito dalla piattaforma |
numpy.csingle
|
float complex
|
rappresentazione dei numeri complessi, composti da una parte reale e immaginaria con una rappresentazione float
|
numpy.cdouble
|
double complex
|
rappresentazione dei numeri complessi, composti da una parte reale e immaginaria con una rappresentazione double
|
numpy.clongdouble
|
long double complex
|
rappresentazione dei numeri complessi, composti da una parte reale e immaginaria con una precisione long double
|
Poiché molti di questi hanno definizioni dipendenti dalla piattaforma, viene fornito un set di alias a dimensione fissa come ad esempio:
numpy.int32
numpy.int64
numpy.float32
numpy.float64 / numpy.float_
numpy.complex64
I tipi di dati possono essere usati come funzioni per convertire i numeri Python in scalari di array (vedere la sezione scalare degli array per una spiegazione), sequenze di numeri Python in array di quel tipo o come argomenti per la parola chiave dtype
che molte funzioni o metodi numpy accettano. Vediamo qualche esempio.
Conversione di un int
in float
x = np.float32(1)
1.0
Conversione di un array di int
float
floatarray = np.float_([1,2,4])
array([1., 2., 4.])
Creazione di un array di tre elementi di tipo complex64
array_dtype_complex64 = np.arange(3, dtype=np.complex64)
array([0.+0.j, 1.+0.j, 2.+0.j], dtype=complex64)
Definizione dei tipi tramite stringa
Per semplificare il più possibile la definizione dei dtype
è possibile anche sfruttare la nomenclatura basata sul singolo carattere o su una stringa composta da due o più caratteri dove:
- il primo carattere specifica il tipo di dato;
- i caratteri rimanenti specificano il numero di byte per elemento.
In quest’ultimo caso, l’unica eccezione è per il tipo unicode
La nomenclatura per il primo carattere è la seguente.
Stringa | Tipo |
---|---|
'?'
|
boolean
|
'b'
|
(signed) byte
|
'B'
|
unsigned byte
|
'i'
|
(signed) integer
|
'u'
|
unsigned integer
|
'f'
|
floating-point
|
'c'
|
complex-floating point
|
'm'
|
timedelta
|
'M'
|
datetime
|
'O'
|
oggetto Python
|
Grazie a questa rappresentazione è possibile definire più velocemente un dtype
o array di elementi. Vediamo qualche esempio.
Per definire un dtype di tipo int32 basterà
dt = np.dtype('i4')
dove i
int
4
dt
dtype('int32')
Per creare un array composto da tre valori di tipo complex128 possiamo definire
complex_array = np.arange(3, dtype=np.dtype('c16'))
il cui valore sarà
array([0.+0.j, 1.+0.j, 2.+0.j])
ed il suo tipo
complex_array.dtype
dtype('complex128')
Gli esempi di questa lezione sono disponibili su GitHub