Skip to content

NumPy : Transformez ndarray en un dtype spécifique avec astype()

Le tableau NumPy ndarray a un type de données dtype, qui peut être spécifié lors de la création d’un objet ndarray avec np.array(). Vous pouvez également le convertir en un autre type avec la méthode astype().

Fondamentalement, un dtype est défini pour un objet ndarray et tous les éléments sont du même type de données.

Cet article décrit le contenu suivant.

  • Liste des types de données de base (dtype) dans NumPy
  • Plage de valeurs (valeurs minimales et maximales) pour les types numériques
  • Le nombre de caractères dans une chaîne
  • object : Stocke des pointeurs vers des objets Python
  • Caster le type de données (dtype) avec astype()
  • Arrondi lors de la coulée du flotteur à l’int
  • Conversions de type implicites

Consultez l’article suivant pour les types de données dtype et astype() dans pandas.

Liste des types de données de base (dtype) dans NumPy

Voici une liste des types de données de base dtype dans NumPy. La plage de valeurs (= valeurs minimales et maximales) pouvant être prises par chaque type d’entier et de nombre à virgule flottante est décrite plus loin.

dtype code de caractère la description
vous8 i1 Entier signé 8 bits
int16 i2 Entier signé 16 bits
int32 i4 Entier signé 32 bits
int64 i8 Entier signé 64 bits
uint8 en 1 Entier non signé 8 bits
uint16 u2 Entier non signé 16 bits
uint32 u4 Entier non signé 32 bits
uint64 u8 Entier non signé 64 bits
float16 f2 Nombre à virgule flottante 16 bits
float32 f4 nombre à virgule flottante 32 bits
float64 f8 Nombre à virgule flottante 64 bits
float128 F 16 nombre à virgule flottante 128 bits
complexe64 c8 Nombre complexe à virgule flottante 64 bits
complexe128 c16 Nombre complexe à virgule flottante 128 bits
complexe256 c32 Nombre complexe à virgule flottante 256 bits
bourdonner ? Booléen (vrai ou faux)
unicode DANS Chaîne Unicode
objet O Objets Python

Les nombres de dtype sont en bit, et les nombres de code de caractère sont en octet. Notez que les nombres sont différents même pour le même type.

Le code de caractère pour le type bool, ? ne signifie pas inconnu, mais littéralement ? est assigné.

Lorsque le type de données dtype est spécifié comme argument de diverses méthodes et fonctions, par exemple, vous pouvez utiliser l’un des éléments suivants pour 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

Il peut également être spécifié en tant que type intégré Python tel que int, float ou str.

Dans ce cas, il est converti en dtype équivalent. Les exemples dans Python3, environnement 64 bits sont les suivants. L’uint n’est pas un type Python, mais est répertorié ensemble pour plus de commodité.

Type Python Exemple de dtype équivalent
entier int64
flotteur float64
chaîne unicode
(uint) uint64

int et la chaîne ‘int’ sont autorisés comme arguments ; seule la chaîne ‘uint’ est autorisée pour uint, qui n’est pas un type 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

Plage de valeurs (valeurs minimales et maximales) pour les types numériques

Vous pouvez utiliser np.iinfo() et np.fininfo() pour vérifier la plage de valeurs possibles pour chaque type de données entier int, uint et nombre à virgule flottante float.

np.iinfo()

Utilisez np.iinfo() pour les entiers int et uint.

Le type numpy.iinfo est renvoyé en spécifiant un objet de type comme argument.

Vous pouvez utiliser print() pour imprimer un résumé et les attributs max et min pour obtenir les valeurs maximales et minimales.

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

Vous pouvez également spécifier une chaîne représentant le dtype comme argument.

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
# ---------------------------------------------------------------
# 

La valeur elle-même peut également être spécifiée comme argument.

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
# ---------------------------------------------------------------
# 

Le tableau NumPy ndarray n’est pas autorisé. Obtenez le type de données avec l’attribut dtype, ou obtenez un élément et spécifiez-le.

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()

Utilisez np.fininfo() pour les nombres à virgule flottante float.

L’utilisation est la même que pour np.iinfo().

L’argument peut être un objet de type (np.float64), une chaîne (‘float64’, ‘f8’) ou une valeur (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

Comme indiqué dans l’exemple ci-dessus, vous pouvez obtenir epsilon avec eps, le nombre de bits dans les parties exponentielles et mantisse avec iexp et nmant, etc.

Voir la documentation officielle ci-dessus pour plus de détails.

Le nombre de caractères dans une chaîne

Si vous utilisez str ou unicode, dtype est comme <U1.

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

< et > indiquent respectivement le petit-boutiste et le gros-boutiste.

Le nombre à la fin indique le nombre de caractères. C’est le nombre maximum de caractères parmi tous les éléments si dtype est spécifié comme str ou unicode dans np.array(), comme dans cet exemple.

Étant donné que seul ce nombre de caractères est alloué pour chaque élément, les chaînes contenant plus de ce nombre de caractères sont tronquées.

Vous pouvez spécifier un type avec un nombre suffisant de caractères au préalable.

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']

object : Stocke des pointeurs vers des objets Python

Le type d’objet est un type de données spécial qui stocke des pointeurs vers des objets Python.

Étant donné que chaque entité de données de chaque élément alloue sa propre zone mémoire, il est possible d’avoir des (pointeurs vers) des données de plusieurs types dans un seul tableau.

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'>

Vous pouvez également modifier le nombre de caractères.

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

Notez que de tels tableaux avec plusieurs types peuvent également être réalisés avec le type de liste intégré de Python.

list et numpy.ndarray ont des comportements différents pour les opérateurs. Dans le cas de ndarray, il est facile d’effectuer des opérations sur chaque élément.

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']

Caster le type de données (dtype) avec astype()

La méthode astype() de numpy.ndarray peut convertir le type de données dtype.

Un nouveau ndarray est créé avec un nouveau dtype, et le ndarray d’origine n’est pas modifié.

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

Comme mentionné ci-dessus, dtype peut être spécifié de différentes manières.

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

Arrondi lors de la coulée du flotteur à l’int

Lors de la conversion de float à int, la virgule décimale est tronquée et arrondie vers 0.

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() et np.around() arrondissent à la valeur paire la plus proche. 0,5 peut être arrondi à 0 au lieu de 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]]

Si vous définissez la fonction suivante, 0,5 est arrondi à 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 fonction ci-dessus arrondit -0,5 à 0. Si vous souhaitez arrondir -0,5 à -1, la fonction doit être la suivante.

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]]

Conversions de type implicites

En plus de la conversion de type explicite par astype(), la conversion de type implicite peut être effectuée par certaines opérations.

Par exemple, la division par l’opérateur / renvoie un nombre à virgule flottante 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

Pour +, -, *, // et **, le résultat est int si tous sont compris entre int et float s’ils contiennent 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

Il en va de même pour les opérations entre numpy.ndarray.

Aussi, même entre int, si le nombre de bits est différent, le type est converti.

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

Comme dans cet exemple, vous pouvez supposer que le type de données est essentiellement converti en celui contenant la plus grande quantité de données.

Cependant, dans certains cas, le type peut être différent de l’un des numpy.ndarray d’origine. Si le nombre de bits est important, il est préférable de le convertir explicitement dans le type souhaité avec astype().

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

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

Notez que le type de numpy.ndarray n’est pas converti lors de l’attribution d’une valeur à un élément.

Par exemple, si vous affectez une valeur flottante à un entier numpy.ndarray, le type de données de numpy.ndarray est toujours int. La valeur attribuée est tronquée après la virgule décimale.

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

print(ones_int16.dtype)
# int16