Vous disposez de quatre options principales pour convertir les types dans pandas :
-
to_numeric()
- fournit une fonctionnalité permettant de convertir en toute sécurité des types non numériques (par exemple, des chaînes de caractères) en un type numérique approprié. (Voir aussi to_datetime()
y to_timedelta()
.)
-
astype()
- convertir (presque) tous les types en (presque) tous les autres types (même s'il n'est pas forcément judicieux de le faire). Permet également de convertir en catégoriel (très utile).
-
infer_objects()
- une méthode utilitaire pour convertir les colonnes d'objets contenant des objets Python en un type pandas si possible.
-
convert_dtypes()
- convertir les colonnes de DataFrame au "meilleur" dtype possible qui supporte pd.NA
(objet de pandas pour indiquer une valeur manquante).
Lisez la suite pour des explications plus détaillées et l'utilisation de chacune de ces méthodes.
1. to_numeric()
La meilleure façon de convertir une ou plusieurs colonnes d'un DataFrame en valeurs numériques est d'utiliser la méthode suivante pandas.to_numeric()
.
Cette fonction essaiera de transformer les objets non numériques (tels que les chaînes de caractères) en nombres entiers ou en nombres à virgule flottante, selon le cas.
Utilisation de base
L'entrée de l to_numeric()
est une série ou une colonne unique d'un DataFrame.
>>> s = pd.Series(["8", 6, "7.5", 3, "0.9"]) # mixed string and numeric values
>>> s
0 8
1 6
2 7.5
3 3
4 0.9
dtype: object
>>> pd.to_numeric(s) # convert everything to float values
0 8.0
1 6.0
2 7.5
3 3.0
4 0.9
dtype: float64
Comme vous pouvez le voir, une nouvelle série est renvoyée. N'oubliez pas d'affecter cette sortie à une variable ou à un nom de colonne pour continuer à l'utiliser :
# convert Series
my_series = pd.to_numeric(my_series)
# convert column "a" of a DataFrame
df["a"] = pd.to_numeric(df["a"])
Vous pouvez également l'utiliser pour convertir plusieurs colonnes d'un DataFrame via la fonction apply()
méthode :
# convert all columns of DataFrame
df = df.apply(pd.to_numeric) # convert all columns of DataFrame
# convert just columns "a" and "b"
df[["a", "b"]] = df[["a", "b"]].apply(pd.to_numeric)
Tant que vos valeurs peuvent toutes être converties, c'est probablement tout ce dont vous avez besoin.
Traitement des erreurs
Mais que faire si certaines valeurs ne peuvent pas être converties en un type numérique ?
to_numeric()
prend également un errors
qui vous permet de forcer des valeurs non numériques à être NaN
ou simplement ignorer les colonnes contenant ces valeurs.
Voici un exemple utilisant une série de chaînes de caractères s
qui a le dtype de l'objet :
>>> s = pd.Series(['1', '2', '4.7', 'pandas', '10'])
>>> s
0 1
1 2
2 4.7
3 pandas
4 10
dtype: object
Le comportement par défaut est de relancer le système s'il ne peut pas convertir une valeur. Dans ce cas, il ne peut pas convertir la chaîne de caractères 'pandas' :
>>> pd.to_numeric(s) # or pd.to_numeric(s, errors='raise')
ValueError: Unable to parse string
Plutôt que d'échouer, nous pourrions vouloir que 'pandas' soit considéré comme une valeur numérique manquante/mauvaise. Nous pouvons contraindre les valeurs invalides à NaN
comme suit en utilisant le errors
l'argument du mot-clé :
>>> pd.to_numeric(s, errors='coerce')
0 1.0
1 2.0
2 4.7
3 NaN
4 10.0
dtype: float64
La troisième option pour errors
consiste simplement à ignorer l'opération si une valeur non valide est rencontrée :
>>> pd.to_numeric(s, errors='ignore')
# the original Series is returned untouched
Cette dernière option est particulièrement utile pour convertir l'ensemble de votre DataFrame, mais vous ne savez pas lesquelles de nos colonnes peuvent être converties de manière fiable en type numérique. Dans ce cas, il suffit d'écrire :
df.apply(pd.to_numeric, errors='ignore')
La fonction sera appliquée à chaque colonne du DataFrame. Les colonnes qui peuvent être converties en un type numérique seront converties, tandis que les colonnes qui ne le peuvent pas (par exemple, si elles contiennent des chaînes de caractères sans chiffres ou des dates) seront laissées telles quelles.
Coulée descendante
Par défaut, la conversion avec to_numeric()
vous donnera soit un int64
o float64
dtype (ou toute autre largeur d'entier propre à votre plate-forme).
C'est généralement ce que l'on souhaite, mais que se passe-t-il si l'on veut économiser de la mémoire et utiliser un dtype plus compact, tel que float32
o int8
?
to_numeric()
vous donne la possibilité d'effectuer un downcast vers 'integer'
, 'signed'
, 'unsigned'
, 'float'
. Voici un exemple pour une série simple s
de type entier :
>>> s = pd.Series([1, 2, -7])
>>> s
0 1
1 2
2 -7
dtype: int64
Diffusion descendante vers 'integer'
utilise le plus petit nombre entier possible qui peut contenir les valeurs :
>>> pd.to_numeric(s, downcast='integer')
0 1
1 2
2 -7
dtype: int8
Diffusion descendante vers 'float'
choisit de la même manière un type flottant plus petit que la normale :
>>> pd.to_numeric(s, downcast='float')
0 1.0
1 2.0
2 -7.0
dtype: float32
2. astype()
El astype()
vous permet d'être explicite quant au type de données que vous voulez donner à votre DataFrame ou à votre série. Elle est très polyvalente dans la mesure où vous pouvez essayer de passer d'un type à un autre.
Utilisation de base
Choisissez simplement un type : vous pouvez utiliser un dtype NumPy (par ex. np.int16
), certains types Python (par exemple bool), ou des types spécifiques à pandas (comme le dtype categorical).
Appelez la méthode sur l'objet que vous voulez convertir et astype()
va essayer de le convertir pour vous :
# convert all DataFrame columns to the int64 dtype
df = df.astype(int)
# convert column "a" to int64 dtype and "b" to complex type
df = df.astype({"a": int, "b": complex})
# convert Series to float16 type
s = s.astype(np.float16)
# convert Series to Python strings
s = s.astype(str)
# convert Series to categorical type - see docs for more details
s = s.astype('category')
Remarquez que j'ai dit "essayer" - si astype()
ne sait pas comment convertir une valeur dans le Series ou le DataFrame, il émet une erreur. Par exemple, si vous avez un NaN
o inf
vous obtiendrez une erreur en essayant de la convertir en un nombre entier.
À partir de la version 0.20.0 de pandas, cette erreur peut être supprimée en passant la commande errors='ignore'
. Votre objet original vous sera rendu intact.
Soyez prudent.
astype()
est puissant, mais il convertit parfois les valeurs de manière "incorrecte". Par exemple :
>>> s = pd.Series([1, 2, -7])
>>> s
0 1
1 2
2 -7
dtype: int64
Il s'agit de petits entiers, alors pourquoi ne pas les convertir en un type 8 bits non signé pour économiser de la mémoire ?
>>> s.astype(np.uint8)
0 1
1 2
2 249
dtype: uint8
La conversion a fonctionné, mais le -7 a été enroulé pour devenir 249 (c'est-à-dire 2 8 - 7) !
J'essaie d'abaisser le niveau en utilisant pd.to_numeric(s, downcast='unsigned')
à la place pourrait aider à prévenir cette erreur.
3. infer_objects()
La version 0.21.0 de pandas a introduit la méthode infer_objects()
pour convertir les colonnes d'un DataFrame qui ont un type de données objet en un type plus spécifique (conversions douces).
Par exemple, voici un DataFrame avec deux colonnes de type objet. L'une contient des entiers réels et l'autre des chaînes de caractères représentant des entiers :
>>> df = pd.DataFrame({'a': [7, 1, 5], 'b': ['3','2','1']}, dtype='object')
>>> df.dtypes
a object
b object
dtype: object
Utilisation de infer_objects()
vous pouvez changer le type de la colonne 'a' en int64 :
>>> df = df.infer_objects()
>>> df.dtypes
a int64
b object
dtype: object
La colonne "b" n'a pas été modifiée car ses valeurs étaient des chaînes de caractères et non des nombres entiers. Si vous vouliez forcer les deux colonnes à un type entier, vous pourriez utiliser df.astype(int)
à la place.
4. convert_dtypes()
Les versions 1.0 et supérieures comprennent une méthode convert_dtypes()
pour convertir les colonnes de Series et de DataFrame dans le meilleur dtype possible qui prend en charge la fonction pd.NA
valeur manquante.
Ici, "le meilleur possible" signifie le type le plus approprié pour contenir les valeurs. Par exemple, il s'agit d'un type pandas integer, si toutes les valeurs sont des entiers (ou des valeurs manquantes) : une colonne d'objets Python integer est convertie en Int64
une colonne de NumPy int32
deviendra le dtype pandas. Int32
.
Avec notre object
Cadre de données df
nous obtenons le résultat suivant :
>>> df.convert_dtypes().dtypes
a Int64
b string
dtype: object
Comme la colonne 'a' contenait des valeurs entières, elle a été convertie au format Int64
(qui peut contenir des valeurs manquantes, à la différence de l'option int64
).
La colonne 'b' contenait des objets de type chaîne, elle a donc été remplacée par la colonne 'pandas'. string
dtype.
Par défaut, cette méthode déduit le type à partir des valeurs des objets dans chaque colonne. Nous pouvons changer cela en passant infer_objects=False
:
>>> df.convert_dtypes(infer_objects=False).dtypes
a object
b string
dtype: object
Maintenant, la colonne 'a' est restée une colonne objet : pandas sait qu'elle peut être décrite comme une colonne 'integer' (en interne, elle s'appelle infer_dtype
) mais n'a pas déduit exactement quel type d'entier il devait avoir et ne l'a donc pas converti. La colonne "b" a de nouveau été convertie en type "string", car elle était reconnue comme contenant des valeurs "string".