Pandas est Excel sur les stéroïdes :la puissante bibliothèque Python vous permet d'analyser des données structurées et tabulaires avec une efficacité et une facilité surprenantes. Pandas est l'une des raisons pour lesquelles les codeurs maîtres atteignent 100 fois l'efficacité des codeurs moyens. Dans l'article d'aujourd'hui, vous apprendrez à travailler avec des données manquantes, en particulier comment gérer les valeurs NaN dans Pandas DataFrames.
Vous découvrirez toutes les différentes raisons pour lesquelles les NaN apparaissent dans vos DataFrames et comment les gérer. Commençons !
Vérification des séries pour les valeurs NaN
Problème :Comment vérifier une série pour les valeurs NaN ?
Jetez un oeil au code suivant :
import pandas as pd import numpy as np data = pd.Series([0, np.NaN, 2]) result = data.hasnans print(result) # True
La série peut contenir NaN
-values :une abréviation pour Not-A-Number —qui décrivent des valeurs indéfinies.
Pour vérifier si une Série contient un ou plusieurs NaN
valeur, utilisez l'attribut hasnans
. L'attribut renvoie True
s'il y a au moins un NaN
valeur et False
Par ailleurs.
Il y a un NaN
valeur dans la série, donc la sortie est True
.
Le filtrage des séries génère NaN
Problème :Lors du filtrage d'une série avec where()
et aucun élément ne passe la condition de filtrage, quel est le résultat ?
import pandas as pd xs = pd.Series([5, 1, 4, 2, 3]) xs.where(xs > 2, inplace=True) result = xs.hasnans print(result) # True
La méthode where()
filtre une série par une condition. Seuls les éléments qui satisfont la condition restent dans la série résultante. Et que se passe-t-il si une valeur ne satisfait pas la condition ? Par défaut, toutes les lignes ne satisfaisant pas la condition sont remplies avec NaN
-valeurs.
C'est pourquoi notre série contient NaN
-values après filtrage avec la méthode where()
.
Travailler avec plusieurs séries de longueurs différentes
Problème :Si vous ajoutez élément par élément deux objets Series avec un nombre différent d'éléments, que se passe-t-il avec les éléments restants ?
import pandas as pd s = pd.Series(range(0, 10)) t = pd.Series(range(0, 20)) result = (s + t)[1] print(result) # 2
Pour ajouter deux éléments de série, utilisez l'opérateur d'addition par défaut +
. La série n'a pas besoin d'avoir la même taille car une fois la première série terminée, les résultats suivants par élément sont NaN
valeurs.
A l'indice 1
dans la série résultante, vous obtenez le résultat de 1 + 1 = 2
.
Créer un DataFrame à partir d'une liste de dictionnaires avec des clés inégales
Problème :Comment créer un DataFrame à partir d'une liste de dictionnaires si les dictionnaires ont des clés inégales ? Un DataFrame s'attend à ce que les mêmes colonnes soient disponibles pour chaque ligne !
import pandas as pd data = [{'Car':'Mercedes', 'Driver':'Hamilton, Lewis'}, {'Car':'Ferrari', 'Driver':'Schumacher, Michael'}, {'Car':'Lamborghini'}] df = pd.DataFrame(data, index=['Rank 2', 'Rank 1', 'Rank 3']) df.sort_index(inplace=True) result = df['Car'].iloc[0] print(result) # Ferrari
Vous pouvez créer un DataFrame à partir d'une liste de dictionnaires. Les clés des dictionnaires définissent les étiquettes des colonnes et les valeurs définissent les entrées des colonnes. Tous les dictionnaires ne doivent pas contenir les mêmes clés. Si un dictionnaire ne contient pas une clé particulière, cela sera interprété comme un NaN
-valeur.
Cet extrait de code utilise des étiquettes de chaîne comme valeurs d'index pour trier le DataFrame. Après avoir trié le DataFrame, la ligne avec l'étiquette d'index Rank 1
est à l'emplacement 0
dans le DataFrame et la valeur dans la colonne Car
est Ferrari
.
Trier un DataFrame par colonne avec des valeurs NaN
Problème :Que se passe-t-il si vous triez un DataFrame par colonne si la colonne contient un NaN
valeur ?
import pandas as pd df = pd.read_csv("Cars.csv") # Dataframe "df" # – -------- # make fuel aspiration body-style price engine-size # 0 audi gas turbo sedan 30000 2.0 # 1 dodge gas std sedan 17000 1.8 # 2 mazda diesel std sedan 17000 NaN # 3 porsche gas turbo convertible 120000 6.0 # 4 volvo diesel std sedan 25000 2.0 # – -------- selection = df.sort_values(by="engine-size") result = selection.index.to_list()[0] print(result) # 1
Dans cet extrait de code, vous triez les lignes du DataFrame par les valeurs de la colonne engine-size
.
Le point principal est que NaN
les valeurs sont toujours déplacées à la fin dans le tri Pandas. Ainsi, la première valeur est 1.8
, qui appartient à la ligne avec la valeur d'index 1
.
Compter les valeurs non-NaN
Problème :Comment compter le nombre d'éléments dans une colonne de dataframe qui ne sont pas Nan
?
import pandas as pd df = pd.read_csv("Cars.csv") # Dataframe "df" # – -------- # make fuel aspiration body-style price engine-size # 0 audi gas turbo sedan 30000 2.0 # 1 dodge gas std sedan 17000 1.8 # 2 mazda diesel std sedan 17000 NaN # 3 porsche gas turbo convertible 120000 6.0 # 4 volvo diesel std sedan 25000 2.0 # – -------- df.count()[5] print(result) # 4
La méthode count()
renvoie le nombre de non-NaN
valeurs pour chaque colonne. Le DataFrame df
a cinq rangées. La cinquième colonne
contient un NaN
évaluer. Par conséquent, le nombre de la cinquième colonne est 4
.
Supprimer les valeurs NaN
Problème :comment supprimer toutes les lignes contenant un NaN
valeur dans l'une de ses colonnes - et comment limiter cela à certaines colonnes ?
import pandas as pd df = pd.read_csv("Cars.csv") # Dataframe "df" # – -------- # make fuel aspiration body-style price engine-size # 0 audi gas turbo sedan 30000 2.0 # 1 dodge gas std sedan 17000 1.8 # 2 mazda diesel std sedan 17000 NaN # 3 porsche gas turbo convertible 120000 6.0 # 4 volvo diesel std sedan 25000 2.0 # – -------- selection1 = df.dropna(subset=["price"]) selection2 = df.dropna() print(len(selection1), len(selection2)) # 5 4
Le dropna()
du DataFrame la méthode supprime toutes les lignes contenant un NaN
valeur dans l'une de ses colonnes. Mais comment restreindre les colonnes à scanner pour NaN
valeurs ?
En passant une liste d'étiquettes de colonne au paramètre facultatif subset
, vous pouvez définir les colonnes que vous souhaitez prendre en compte.
L'appel du dropna()
sans restriction, abandonne la ligne 2
à cause du NaN
valeur dans la colonne engine-size
. Lorsque vous limitez les colonnes uniquement à price
, aucune ligne ne sera supprimée, car aucun NaN
la valeur est présente.
Supprimer Nan et réinitialiser l'index
Problème :Qu'arrive-t-il aux index après avoir supprimé certaines lignes ?
import pandas as pd df = pd.read_csv("Cars.csv") # Dataframe "df" # – -------- # make fuel aspiration body-style price engine-size # 0 audi gas turbo sedan 30000 2.0 # 1 dodge gas std sedan 17000 1.8 # 2 mazda diesel std sedan 17000 NaN # 3 porsche gas turbo convertible 120000 6.0 # 4 volvo diesel std sedan 25000 2.0 # – -------- df.drop([0, 1, 2], inplace=True) df.reset_index(inplace=True) result = df.index.to_list() print(result) # [0, 1]
La méthode drop()
sur un DataFrame supprime les lignes ou les colonnes par index. Vous pouvez transmettre une valeur unique ou une liste de valeurs.
Par défaut le inplace
le paramètre est défini sur False
, afin que les modifications n'affectent pas l'objet DataFrame initial. Au lieu de cela, la méthode renvoie une copie modifiée du DataFrame. Dans le puzzle, vous définissez inplace
à True
, donc les suppressions sont effectuées directement sur le DataFrame.
Après avoir supprimé les trois premières lignes, les deux premières étiquettes d'index sont 3 et 4. Vous pouvez réinitialiser l'indexation par défaut en appelant la méthode reset_index()
sur le DataFrame, de sorte que l'index recommence à 0. Comme il ne reste que deux lignes dans le DataFrame, le résultat est [0, 1]
.
Concaténation de DataFrames dissemblables remplis de NaN
Problème :Comment concaténer deux DataFrames si elles ont des colonnes différentes ?
import pandas as pd df = pd.read_csv("Cars.csv") df2 = pd.read_csv("Cars2.csv") # Dataframe "df" # – -------- # make fuel aspiration body-style price engine-size # 0 audi gas turbo sedan 30000 2.0 # 1 dodge gas std sedan 17000 1.8 # 2 mazda diesel std sedan 17000 NaN # 3 porsche gas turbo convertible 120000 6.0 # 4 volvo diesel std sedan 25000 2.0 # – -------- # Additional Dataframe "df2" # – -------- # make origin # 0 skoda Czechia # 1 toyota Japan # 2 ford USA # – -------- try: result = pd.concat([df, df2], axis=0, ignore_index=True) print("Y") except Exception: print ("N") # Y
Même si les DataFrames ont des colonnes différentes, vous pouvez les concaténer.
Si DataFrame 1 a les colonnes A et B et DataFrame 2 a les colonnes C et D, le résultat de la concaténation des DataFrames 1 et 2 est un DataFrame avec les colonnes A, B, C et D. Les valeurs manquantes dans les lignes sont remplies avec NaN
.
Fusion externe
Problème :Lors de la fusion (=assemblage) de deux DataFrames, que se passe-t-il s'il manque des valeurs ?
import pandas as pd df = pd.read_csv("Cars.csv") df2 = pd.read_csv("Cars2.csv") # Dataframe "df" # – -------- # make fuel aspiration body-style price engine-size # 0 audi gas turbo sedan 30000 2.0 # 1 dodge gas std sedan 17000 1.8 # 2 mazda diesel std sedan 17000 NaN # 3 porsche gas turbo convertible 120000 6.0 # 4 volvo diesel std sedan 25000 2.0 # – -------- # Additional dataframe "df2" # – -------- # make origin # 0 skoda Czechia # 1 mazda Japan # 2 ford USA # – -------- result = pd.merge(df, df2, how="outer", left_on="make", right_on="make") print(len(result["fuel"])) print(result["fuel"].count()) # 7 # 5
Avec la fonction Panda merge()
et le paramètre how
défini sur outer
, vous pouvez effectuer une jointure externe .
Le DataFrame résultant d'une jointure externe contient toutes les valeurs des deux DataFrames d'entrée ; les valeurs manquantes sont remplies avec NaN
.
De plus, ce puzzle montre comment NaN
les valeurs sont comptées par le len()
alors que la méthode count()
n'inclut pas NaN
valeurs.
Remplacement de NaN
Problème :Comment remplacer tous les NaN
valeurs dans un DataFrame avec une valeur donnée ?
import pandas as pd df = pd.read_csv("Cars.csv") # Dataframe "df" # – -------- # make fuel aspiration body-style price engine-size # 0 audi gas turbo sedan 30000 2.0 # 1 dodge gas std sedan 17000 1.8 # 2 mazda diesel std sedan 17000 NaN # 3 porsche gas turbo convertible 120000 6.0 # 4 volvo diesel std sedan 25000 2.0 # – -------- df.fillna(2.0, inplace=True) result = df["engine-size"].sum() print(result) # 13.8
La méthode fillna()
remplace NaN
valeurs avec une nouvelle valeur. Ainsi, la somme de toutes les valeurs de la colonne engine-size
est de 13,8.
Différence entre la longueur et le nombre :c'est NaN !
Problème :Quelle est la différence entre le len()
et le count()
fonctions ?
import pandas as pd df = pd.read_csv("Cars.csv") df2 = pd.read_csv("Cars2.csv") # Dataframe "df" # – -------- # make fuel aspiration body-style price engine-size # 0 audi gas turbo sedan 30000 2.0 # 1 dodge gas std sedan 17000 1.8 # 2 mazda diesel std sedan 17000 NaN # 3 porsche gas turbo convertible 120000 6.0 # 4 volvo diesel std sedan 25000 2.0 # – -------- # Additional dataframe "df2" # – -------- # make origin # 0 skoda Czechia # 1 mazda Japan # 2 ford USA # – -------- result = pd.merge(df2, df, how="left", left_on="make", right_on="make") print(len(result["fuel"])) print(result["fuel"].count()) # 3 # 1
Dans une jointure gauche, le DataFrame gauche est le maître et toutes ses valeurs sont incluses dans le DataFrame résultant.
Par conséquent, le résultat DataFrame contient trois lignes, mais depuis skoda
et ford
n'apparaissent pas dans DataFrame df
, une seule ligne pour mazda
contient une valeur.
Encore une fois, nous voyons la différence entre l'utilisation de la fonction len()
qui comprend également NaN
valeurs et la méthode count()
qui ne compte pas NaN
valeurs.
Equals() vs. ==lors de la comparaison de NaN
Problème :
import pandas as pd df = pd.read_csv("Cars.csv") # Dataframe "df" # – -------- # make fuel aspiration body-style price engine-size # 0 audi gas turbo sedan 30000 2.0 # 1 dodge gas std sedan 17000 1.8 # 2 mazda diesel std sedan 17000 NaN # 3 porsche gas turbo convertible 120000 6.0 # 4 volvo diesel std sedan 25000 2.0 # – -------- df["engine-size_copy"] = df["engine-size"] check1 = (df["engine-size_copy"] == df["engine-size"]).all() check2 = df["engine-size_copy"].equals(df["engine-size"]) print(check1 == check2) # False
Cet extrait de code montre comment comparer des colonnes ou des DataFrames entiers concernant la forme et les éléments.
La comparaison utilisant l'opérateur ==
renvoie False
pour notre DataFrame car la comparaison NaN
-valeurs avec ==
donne toujours False
.
Par contre, df.equals()
permet de comparer deux Series ou DataFrames. Dans ce cas, NaN
-les valeurs au même endroit sont considérées comme égales.
Les en-têtes de colonne n'ont pas besoin d'avoir le même type, mais les éléments dans les colonnes doivent être du même dtype
.
Depuis le résultat de check1
est False
et le résultat de check2
donne True
, la sortie finale est False
.