Skip to content

NumPy: Fissare ndarray a un tipo specifico con astype()

Python

L’array NumPy ndarray ha un tipo di dati dtype, che può essere specificato durante la creazione di un oggetto ndarray con np.array(). Puoi anche convertirlo in un altro tipo con il metodo astype().

Fondamentalmente, un dtype è impostato per un oggetto ndarray e tutti gli elementi sono dello stesso tipo di dati.

In questo articolo vengono descritti i seguenti contenuti.

  • Elenco dei tipi di dati di base (dtype) in NumPy
  • Intervallo di valori (valori minimi e massimi) per i tipi numerici
  • Il numero di caratteri in una stringa
  • oggetto: memorizzati i puntatori agli oggetti Python
  • Trasmetti il ​​tipo di dati (dtype) con astype()
  • Arrotondamento quando si lancia da float a int
  • Conversioni di tipo implicito

Vedere l’articolo seguente per i tipi di dati dtype e astype() nei panda.

Elenco dei tipi di dati di base (dtype) in NumPy

Di seguito è riportato un elenco di tipi di dati di base dtype in NumPy. L’intervallo di valori (= valori minimo e massimo) che può essere assunto da ciascun tipo di numero intero e in virgola mobile è in seguito.

tipo d codice carattere descrizione
int8 i1 Intero con segno a 8 bit
int16 i2 Intero con segno a 16 bit
int32 i4 Intero con segno a 32 bit
int64 i8 Intero con segno a 64 bit
uint8 u1 Intero senza segno a 8 bit
uint16 u2 Intero senza segno a 16 bit
uint32 u4 Intero senza segno a 32 bit
uint64 u8 Intero senza segno a 64 bit
galleggiante16 f2 Numero a virgola mobile a 16 bit
galleggiante32 f4 Numero a virgola mobile a 32 bit
galleggiante64 f8 Numero a virgola mobile a 64 bit
galleggiante128 f16 Numero a virgola mobile a 128 bit
complesso64 c8 Numero a virgola mobile complesso a 64 bit
complesso128 c16 Numero a virgola mobile complesso a 128 bit
complesso256 c32 Numero a virgola mobile complesso a 256 bit
bollo ? Booleano (vero o falso)
unicode tu Stringa Unicode
oggetto o Oggetti Python

I numeri di dtype sono in bit ei numeri di codice carattere sono in byte. Si noti che i numeri sono diversi anche per lo stesso tipo.

Il codice del carattere per il tipo bool, ? non significa sconosciuto, ma letteralmente ? è assegnato.

Quando il tipo di dati dtype viene specificato come argomento di vari metodi e funzioni, ad esempio, è possibile utilizzare uno dei seguenti per int64:

import numpy as np

a = np.array([1, 2, 3], dtype=np.int64)
print(a.dtype)
# int64

a = np.array([1, 2, 3], dtype='int64')
print(a.dtype)
# int64

a = np.array([1, 2, 3], dtype='i8')
print(a.dtype)
# int64

Può anche essere specificato come tipo integrato in Python come int, float o str.

In questo caso, viene convertito nell’equivalente dtype. Esempi in Python3, ambiente a 64 bit sono i seguenti. uint non è un tipo Python, ma è elencato insieme per comodità.

Tipo Python Esempio di dtype equivalente
int int64
galleggiante galleggiante64
str unicode
(uint) uint64

Sia int che la stringa ‘int’ sono consentiti come argomenti; solo la stringa ‘uint’ è consentita per uint, che non è un tipo Python.

print(int is np.int)
# True

a = np.array([1, 2, 3], dtype=int)
print(a.dtype)
# int64

a = np.array([1, 2, 3], dtype='int')
print(a.dtype)
# int64

Intervallo di valori (valori minimi e massimi) per i tipi numerici

È possibile utilizzare np.iinfo() e np.fininfo() per controllare l’intervallo di valori possibili per ciascun tipo di dati di intero int, uint e numero a virgola mobile float.

np.iinfo()

Usa np.iinfo() per gli interi int e uint.

Il tipo numpy.iinfo viene restituito specificando un oggetto di tipo come argomento.

È possibile utilizzare print() per stampare un riepilogo e gli attributi max e min per ottenere i valori massimo e minimo.

ii64 = np.iinfo(np.int64)
print(type(ii64))
# <class 'numpy.iinfo'>

print(ii64)
# Machine parameters for int64
# ---------------------------------------------------------------
# min = -9223372036854775808
# max = 9223372036854775807
# ---------------------------------------------------------------
# 

print(ii64.max)
# 9223372036854775807

print(type(ii64.max))
# <class 'int'>

print(ii64.min)
# -9223372036854775808

print(ii64.bits)
# 64

Puoi anche specificare una stringa che rappresenta il tipo come argomento.

print(np.iinfo('int16'))
# Machine parameters for int16
# ---------------------------------------------------------------
# min = -32768
# max = 32767
# ---------------------------------------------------------------
# 

print(np.iinfo('i4'))
# Machine parameters for int32
# ---------------------------------------------------------------
# min = -2147483648
# max = 2147483647
# ---------------------------------------------------------------
# 

print(np.iinfo(int))
# Machine parameters for int64
# ---------------------------------------------------------------
# min = -9223372036854775808
# max = 9223372036854775807
# ---------------------------------------------------------------
# 

print(np.iinfo('uint64'))
# Machine parameters for uint64
# ---------------------------------------------------------------
# min = 0
# max = 18446744073709551615
# ---------------------------------------------------------------
# 

Il valore stesso può anche essere specificato come argomento.

i = 100
print(type(i))
# <class 'int'>

print(np.iinfo(i))
# Machine parameters for int64
# ---------------------------------------------------------------
# min = -9223372036854775808
# max = 9223372036854775807
# ---------------------------------------------------------------
# 

ui = np.uint8(100)
print(type(ui))
# <class 'numpy.uint8'>

print(np.iinfo(ui))
# Machine parameters for uint8
# ---------------------------------------------------------------
# min = 0
# max = 255
# ---------------------------------------------------------------
# 

NumPy array ndarray non è consentito. Ottieni il tipo di dati con l’attributo dtype o ottieni un elemento e specificalo.

a = np.array([1, 2, 3], dtype=np.int8)
print(type(a))
# <class 'numpy.ndarray'>

# print(np.iinfo(a))
# ValueError: Invalid integer data type 'O'.

print(np.iinfo(a.dtype))
# Machine parameters for int8
# ---------------------------------------------------------------
# min = -128
# max = 127
# ---------------------------------------------------------------
# 

print(np.iinfo(a[0]))
# Machine parameters for int8
# ---------------------------------------------------------------
# min = -128
# max = 127
# ---------------------------------------------------------------
# 

np.finfo()

Usa np.fininfo() per i numeri in virgola mobile float.

L’utilizzo è lo stesso di np.iinfo().

L’argomento può essere un oggetto di tipo (np.float64), una stringa (‘float64’, ‘f8’) o un valore (0.1).

fi64 = np.finfo(np.float64)
print(type(fi64))
# <class 'numpy.finfo'>

print(fi64)
# Machine parameters for float64
# ---------------------------------------------------------------
# precision =  15   resolution = 1.0000000000000001e-15
# machep =    -52   eps =        2.2204460492503131e-16
# negep =     -53   epsneg =     1.1102230246251565e-16
# minexp =  -1022   tiny =       2.2250738585072014e-308
# maxexp =   1024   max =        1.7976931348623157e+308
# nexp =       11   min =        -max
# ---------------------------------------------------------------
# 

print(fi64.max)
# 1.7976931348623157e+308

print(type(fi64.max))
# <class 'numpy.float64'>

print(fi64.min)
# -1.7976931348623157e+308

print(fi64.eps)
# 2.220446049250313e-16

print(fi64.bits)
# 64

print(fi64.iexp)
# 11

print(fi64.nmant)
# 52

Come mostrato nell’esempio sopra, puoi ottenere epsilon con eps, numero di bit in parti esponenziali e mantissa con iexp e nmant e così via.

Vedere la documentazione ufficiale sopra per i dettagli.

Il numero di caratteri in una stringa

Se usi str o unicode, dtype è come <U1.

a_str = np.array([1, 2, 3], dtype=str)
print(a_str)
print(a_str.dtype)
# ['1' '2' '3']
# <U1

< e > invece indica little-endian e big-endian.

Il numero alla fine indica il numero di caratteri. È il numero massimo di caratteri tra tutti gli elementi se dtype è specificato come str o unicode in np.array(), come in questo esempio.

Poiché per ogni elemento viene allocato solo questo numero di caratteri, le stringhe con un numero di superiore a questo numero vengono troncate.

È possibile specificare in anticipo un tipo con un numero sufficiente di caratteri.

a_str[0] = 'abcde'
print(a_str)
# ['a' '2' '3']

a_str10 = np.array([1, 2, 3], dtype='U10')
print(a_str10.dtype)
# <U10

a_str10[0] = 'abcde'
print(a_str10)
# ['abcde' '2' '3']

oggetto: memorizzati i puntatori agli oggetti Python

Il tipo di oggetto è un tipo di dati speciali che memorizza i puntatori agli oggetti Python.

Poiché ogni entità di dati di ogni elemento alloca la propria area di memoria, è possibile avere (puntatori a) dati di più tipi in un singolo array.

a_object = np.array([1, 0.1, 'one'], dtype=object)
print(a_object)
print(a_object.dtype)
# [1 0.1 'one']
# object

print(type(a_object[0]))
print(type(a_object[1]))
print(type(a_object[2]))
# <class 'int'>
# <class 'float'>
# <class 'str'>

Puoi anche modificare il numero di caratteri.

a_object[2] = 'oneONE'
print(a_object)
# [1 0.1 'oneONE']

Si noti che tali array con più tipi possono essere realizzati anche con il tipo di elenco integrato di Python.

list e numpy.ndarray hanno comportamenti diversi per gli operatori. Nel caso di ndarray, è facile eseguire operazioni su ogni elemento.

l = [1, 0.1, 'oneONE']
print(type(l[0]))
print(type(l[1]))
print(type(l[2]))
# <class 'int'>
# <class 'float'>
# <class 'str'>

print(a_object * 2)
# [2 0.2 'oneONEoneONE']

print(l * 2)
# [1, 0.1, 'oneONE', 1, 0.1, 'oneONE']

Trasmetti il ​​tipo di dati (dtype) con astype()

Il metodo astype() di numpy.ndarray può adottare il tipo di dati dtype.

Viene creato un nuovo ndarray con un nuovo dtype e il ndarray originale non viene modificato.

import numpy as np

a = np.array([1, 2, 3])
print(a)
print(a.dtype)
# [1 2 3]
# int64

a_float = a.astype(np.float32)
print(a_float)
print(a_float.dtype)
# [1. 2. 3.]
# float32

print(a)
print(a.dtype)
# [1 2 3]
# int64

Come accennato in precedenza, dtype può essere specificato in vari modi.

a_float = a.astype(float)
print(a_float)
print(a_float.dtype)
# [1. 2. 3.]
# float64

a_str = a.astype('str')
print(a_str)
print(a_str.dtype)
# ['1' '2' '3']
# <U21

a_int = a.astype('int32')
print(a_int)
print(a_int.dtype)
# [1 2 3]
# int32

Arrotondamento quando si lancia da float a int

Quando si esegue il cast da float a int, il punto decimale viene troncato e arrotondato per difetto.

a = np.arange(50).reshape((5, 10)) / 10 - 2
print(a)
print(a.dtype)
# [[-2.  -1.9 -1.8 -1.7 -1.6 -1.5 -1.4 -1.3 -1.2 -1.1]
#  [-1.  -0.9 -0.8 -0.7 -0.6 -0.5 -0.4 -0.3 -0.2 -0.1]
#  [ 0.   0.1  0.2  0.3  0.4  0.5  0.6  0.7  0.8  0.9]
#  [ 1.   1.1  1.2  1.3  1.4  1.5  1.6  1.7  1.8  1.9]
#  [ 2.   2.1  2.2  2.3  2.4  2.5  2.6  2.7  2.8  2.9]]
# float64

a_int = a.astype('int64')
print(a_int)
print(a_int.dtype)
# [[-2 -1 -1 -1 -1 -1 -1 -1 -1 -1]
#  [-1  0  0  0  0  0  0  0  0  0]
#  [ 0  0  0  0  0  0  0  0  0  0]
#  [ 1  1  1  1  1  1  1  1  1  1]
#  [ 2  2  2  2  2  2  2  2  2  2]]
# int64

np.round() e np.around() arrotonda al valore pari più vicino. 0,5 può essere arrotondato a 0 anziché a 1.

print(np.round(a).astype(int))
# [[-2 -2 -2 -2 -2 -2 -1 -1 -1 -1]
#  [-1 -1 -1 -1 -1  0  0  0  0  0]
#  [ 0  0  0  0  0  0  1  1  1  1]
#  [ 1  1  1  1  1  2  2  2  2  2]
#  [ 2  2  2  2  2  2  3  3  3  3]]

Se si definisce la funzione seguente, 0,5 viene arrotondato a 1.

my_round_int = lambda x: np.round((x * 2 + 1) // 2)

print(my_round_int(a).astype(int))
# [[-2 -2 -2 -2 -2 -1 -1 -1 -1 -1]
#  [-1 -1 -1 -1 -1  0  0  0  0  0]
#  [ 0  0  0  0  0  1  1  1  1  1]
#  [ 1  1  1  1  1  2  2  2  2  2]
#  [ 2  2  2  2  2  3  3  3  3  3]]

La funzione sopra arrotondare da -0,5 a 0. Se vuoi arrotondare da -0,5 a -1, la funzione dovrebbe essere la seguente.

def my_round(x, digit=0):
    p = 10 ** digit
    s = np.copysign(1, x)
    return (s * x * p * 2 + 1) // 2 / p * s

print(my_round(a).astype(int))
# [[-2 -2 -2 -2 -2 -2 -1 -1 -1 -1]
#  [-1 -1 -1 -1 -1 -1  0  0  0  0]
#  [ 0  0  0  0  0  1  1  1  1  1]
#  [ 1  1  1  1  1  2  2  2  2  2]
#  [ 2  2  2  2  2  3  3  3  3  3]]

Conversioni di tipo implicito

Oltre alla conversione esplicita del tipo tramite astype(), la conversione implicita del tipo può essere eseguita da alcune operazioni.

Ad esempio, la divisione per l’operatore / riporta un numero a virgola mobile float.

a = np.array([1, 2, 3])
print(a)
print(a.dtype)
# [1 2 3]
# int64

print((a / 1).dtype)
# float64

print((a / 1.0).dtype)
# float64

Per +, -, *, // e **, il risultato è int se sono tutti compresi tra int e float se contengono float.

print((a + 1).dtype)
# int64

print((a + 1.0).dtype)
# float64

print((a - 1).dtype)
# int64

print((a - 1.0).dtype)
# float64

print((a * 1).dtype)
# int64

print((a * 1.0).dtype)
# float64

print((a // 1).dtype)
# int64

print((a // 1.0).dtype)
# float64

print((a ** 1).dtype)
# int64

print((a ** 1.0).dtype)
# float64

Lo stesso vale per le operazioni tra numpy.ndarray.

Inoltre, anche tra int, se il numero di bit è diverso, il tipo viene convertito.

ones_int16 = np.ones(3, np.int16)
print(ones_int16)
# [1 1 1]

ones_int32 = np.ones(3, np.int32)
print(ones_int32)
# [1 1 1]

print((ones_int16 + ones_int32).dtype)
# int32

Vieni in questo esempio, puoi presumere che il tipo di dati sia convertito in quello con la quantità maggiore di dati.

Tuttavia, in alcuni casi, il tipo potrebbe essere diverso da qualsiasi numpy.ndarray originale. Se il numero di bit è importante, è meglio convertirlo nel tipo desiderato con astype().

ones_float16 = np.ones(3, np.float16)
print(ones_float16)
# [1. 1. 1.]

print((ones_int16 + ones_float16).dtype)
# float32

Si noti che il tipo di numpy.ndarray non viene convertito quando si assegna un valore a un elemento.

Ad esempio, se si assegna un valore float a un numero intero numpy.ndarray, il tipo di dati di numpy.ndarray è ancora int. Il valore ricevuto viene troncato dopo la virgola.

ones_int16[0] = 10.9
print(ones_int16)
# [10  1  1]

print(ones_int16.dtype)
# int16