
4 concepts Pandas qui brisent silencieusement vos pipelines de données
J’ai commencé à utiliser Pandas, je pensais que j’allais plutôt bien.
Je pourrais nettoyer les ensembles de données, exécuter groupbyfusionnez des tableaux et créez des analyses rapides dans un notebook Jupyter. La plupart des didacticiels ont rendu les choses simples : chargez des données, transformez-les, visualisez-les et vous avez terminé.
Et pour être honnête, mon code est généralement travaillé.
Jusqu’à ce que ce ne soit pas le cas.
À un moment donné, j’ai commencé à rencontrer des problèmes étranges et difficiles à expliquer. Les chiffres ne correspondent pas à ce à quoi je m’attendais. Une colonne qui semblait numérique se comportait comme du texte. Parfois, une transformation se déroulait sans erreur mais produisait des résultats clairement erronés.
Le plus frustrant était que les Pandas se plaignaient rarement.
Il n’y a eu aucune exception ni crash évident. Le code s’est très bien exécuté – il a simplement produit des résultats incorrects.
C’est alors que j’ai réalisé quelque chose d’important : la plupart des tutoriels Pandas se concentrent sur ce que tu peux fairemais ils expliquent rarement comment les pandas se comportent réellement sous le capot.
Des choses comme :
- Comment les Pandas gèrent types de données
- Comment alignement des index travaux
- La différence entre un copie et vue
- et comment écrire code de manipulation de données défensives
Ces concepts ne semblent pas passionnants lorsque vous apprenez pour la première fois Pandas. Ils ne sont pas aussi flashy que groupby astuces ou visualisations fantaisistes.
Mais ce sont exactement ces choses qui empêchent bugs silencieux dans les pipelines de données du monde réel.
Dans cet article, je vais passer en revue quatre concepts Pandas que la plupart des didacticiels ignorent – les mêmes qui provoquaient sans cesse des bugs subtils dans mon propre code.
Si vous comprenez ces idées, vos flux de travail Pandas deviennent beaucoup plus fiables, surtout lorsque votre analyse commence à se transformer en des pipelines de données de production au lieu de blocs-notes uniques.
Commençons par l’une des sources de problèmes les plus courantes : types de données.
Un petit ensemble de données (et un bug subtil)
Pour concrétiser ces idées, travaillons avec un petit ensemble de données de commerce électronique.
Imaginez que nous analysons les commandes d’une boutique en ligne. Chaque ligne représente une commande et comprend des informations sur les revenus et les remises.
import pandas as pd
orders = pd.DataFrame({
"order_id": [1001, 1002, 1003, 1004],
"customer_id": [1, 2, 2, 3],
"revenue": ["120", "250", "80", "300"], # looks numeric
"discount": [None, 10, None, 20]
})
orders
Sortir:

À première vue, tout semble normal. Nous avons des valeurs de revenus, des remises et quelques entrées manquantes.
Répondons maintenant à une question simple :
Quel est le revenu total ?
orders["revenue"].sum()
Vous pourriez vous attendre à quelque chose comme :
750
Au lieu de cela, Pandas renvoie :
'12025080300'
C’est un exemple parfait de ce que j’ai mentionné plus tôt : Les pandas échouent souvent en silence. Le code s’exécute correctement, mais le résultat n’est pas celui attendu.
La raison est subtile mais incroyablement importante :
Le revenue La colonne semble être numérique, mais Pandas la stocke en tant que texte.
Nous pouvons le confirmer en vérifiant les types de données du dataframe.
orders.dtypes
Ce petit détail présente l’une des sources de bugs les plus courantes dans les workflows Pandas : types de données.
Réparons cela ensuite.
1. Types de données : la source cachée de nombreux bogues Pandas
Le problème que nous venons de voir se résume à quelque chose de simple : types de données.
Même si le revenue La colonne semble numérique, Pandas l’a interprété comme un objet (essentiellement du texte).
Nous pouvons confirmer que :
orders.dtypes
Sortir:
order_id int64
customer_id int64
revenue object
discount float64
dtype: object
Parce que revenue est stocké sous forme de texte, les opérations se comportent différemment. Lorsque nous avons demandé aux Pandas de résumer la colonne plus tôt, cela chaînes concaténées au lieu d’ajouter des chiffres :
Ce type de problème apparaît étonnamment souvent lorsque l’on travaille avec des ensembles de données réels. Les données exportées à partir de feuilles de calcul, de fichiers CSV ou d’API stockent fréquemment des nombres sous forme de texte.
L’approche la plus sûre consiste à définir explicitement les types de données au lieu de s’appuyer sur les suppositions de Pandas.
Nous pouvons réparer la colonne en utilisant astype():
orders["revenue"] = orders["revenue"].astype(int)
Maintenant, si nous vérifions à nouveau les types :
orders.dtypes
On obtient :
order_id int64
customer_id int64
revenue int64
discount float64
dtype: object
Et le calcul se comporte finalement comme prévu :
orders["revenue"].sum()
Sortir:
750
Une simple habitude défensive
Chaque fois que je charge un nouvel ensemble de données maintenant, l’une des premières choses que j’exécute est :orders.info()
Il donne un aperçu rapide de :
- types de données de colonne
- valeurs manquantes
- utilisation de la mémoire
Cette étape simple révèle souvent des problèmes subtils avant qu’ils ne se transforment en bugs déroutants plus tard.
Mais les types de données ne représentent qu’une partie de l’histoire.
Un autre comportement de Pandas provoque encore plus de confusion, en particulier lors de la combinaison d’ensembles de données ou de l’exécution de calculs.
C’est quelque chose qui s’appelle alignement des index.
Alignement de l’index : Pandas correspond aux étiquettes, pas aux lignes
L’un des comportements les plus puissants – et les plus déroutants – chez les pandas est alignement des index.
Lorsque Pandas effectue des opérations entre des objets (comme des séries ou des DataFrames), il ne correspond pas aux lignes par position.
Au lieu de cela, il les correspond par étiquettes d’index.
Au premier abord, cela semble subtil. Mais il peut facilement produire des résultats qui semblent corrects au premier coup d’œil alors qu’ils sont en réalité erronés.
Voyons un exemple simple.
revenue = pd.Series([120, 250, 80], index=[0, 1, 2])
discount = pd.Series([10, 20, 5], index=[1, 2, 3])
revenue + discount
Le résultat ressemble à ceci :
0 NaN
1 260
2 100
3 NaN
dtype: float64
À première vue, cela peut paraître étrange.
Pourquoi les Pandas ont-ils produit quatre rangées au lieu de trois ?
La raison est que les Pandas ont aligné les valeurs basé sur les étiquettes d’index.
Pandas aligne les valeurs à l’aide de leurs étiquettes d’index. En interne, le calcul ressemble à ceci :
- À indice 0les revenus existent mais pas la remise → le résultat devient
NaN - À indice 1les deux valeurs existent →
250 + 10 = 260 - À indice 2les deux valeurs existent →
80 + 20 = 100 - À indice 3la remise existe mais pas les revenus → le résultat devient
NaN
Ce qui produit :
0 NaN
1 260
2 100
3 NaN
dtype: float64
Les lignes sans indices correspondants produisent des valeurs manquantes, essentiellement.
Ce comportement est en fait l’un des points forts de Pandas car il permet de combiner intelligemment des ensembles de données avec des structures différentes.
Mais cela peut aussi introduire des bugs subtils.
Comment cela apparaît dans une analyse réelle
Revenons à notre orders ensemble de données.
Supposons que nous filtrions les commandes avec des remises :
discounted_orders = orders[orders["discount"].notna()]
Imaginez maintenant que nous essayions de calculer revenu net en soustrayant la remise.
orders["revenue"] - discounted_orders["discount"]
Vous pourriez vous attendre à une simple soustraction.
Au lieu de cela, Pandas aligne les lignes en utilisant le indices originaux.
Le résultat contiendra des valeurs manquantes car la trame de données filtrée n’a plus la même structure d’index.
Cela peut facilement conduire à :
- inattendu
NaNvaleurs - mesures mal calculées
- résultats en aval confus
Et encore — Les pandas ne généreront pas d’erreur.
Une approche défensive
Si vous voulez que les opérations se comportent ligne par ligneune bonne pratique consiste à réinitialiser l’index après le filtrage.
discounted_orders = orders[orders["discount"].notna()].reset_index(drop=True)
Maintenant, les lignes sont à nouveau alignées par position.
Une autre option consiste à aligner explicitement les objets avant d’effectuer des opérations :
orders.align(discounted_orders)
Ou dans les situations où l’alignement n’est pas nécessaire, vous pouvez travailler avec des tableaux bruts :
orders["revenue"].values
En fin de compte, tout se résume à cela.
Dans Pandas, les opérations s’alignent par étiquettes d’indexpas l’ordre des lignes.
Comprendre ce comportement aide à expliquer de nombreux mystères NaN valeurs qui apparaissent lors de l’analyse.
Mais il existe un autre comportement de Pandas qui a dérouté presque tous les analystes de données à un moment donné.
Vous l’avez probablement déjà vu :<strong>SettingWithCopyWarning</strong>
Voyons ce qui s’y passe réellement.
Super – passons à la section suivante.
Le problème de copie ou d’affichage (et le célèbre avertissement)
Si vous utilisez Pandas depuis un certain temps, vous avez probablement déjà vu cet avertissement :
SettingWithCopyWarning
Lorsque je l’ai rencontré pour la première fois, je l’ai pour la plupart ignoré. Le code fonctionnait toujours et le résultat semblait correct, donc cela ne semblait pas très grave.
Mais cet avertissement souligne quelque chose d’important sur le fonctionnement de Pandas : parfois vous modifiez le trame de données originaleet parfois vous modifiez un copie temporaire.
Le plus délicat est que Pandas ne rend pas toujours cela évident.
Regardons un exemple utilisant notre orders ensemble de données.
Supposons que nous souhaitions ajuster les revenus pour les commandes pour lesquelles une remise existe.
Une approche naturelle pourrait ressembler à ceci :
discounted_orders = orders[orders["discount"].notna()]
discounted_orders["revenue"] = discounted_orders["revenue"] - discounted_orders["discount"]
Cela déclenche souvent l’avertissement :
SettingWithCopyWarning:
Une valeur tente d’être définie sur une copie d’une tranche d’un DataFrame
Le problème est que discounted_orders ne peut pas être une trame de données indépendante. C’est peut-être juste un voir dans l’original orders trame de données.
Ainsi, lorsque nous les modifions, Pandas ne sait pas toujours si nous avons l’intention de modifier les données d’origine ou de modifier le sous-ensemble filtré. C’est cette ambiguïté qui produit l’avertissement.
Pire encore, la modification pourrait ne pas se comporter de manière cohérente en fonction de la manière dont le dataframe a été créé. Dans certaines situations, la modification affecte la trame de données d’origine ; dans d’autres, ce n’est pas le cas.
Ce type de comportement imprévisible est exactement le genre de chose qui provoque des bugs subtils dans les flux de travail de données réels.
La manière la plus sûre : utiliser .loc
Une approche plus fiable consiste à modifier le dataframe en utilisant explicitement .loc.
orders.loc[orders["discount"].notna(), "revenue"] = (
orders["revenue"] - orders["discount"]
)
Cette syntaxe indique clairement à Pandas quelles lignes modifier et quelle colonne mettre à jour. L’opération étant explicite, les Pandas peuvent appliquer le changement en toute sécurité et sans ambiguïté.
Une autre bonne habitude : utiliser .copy()
Parfois, vous souhaitez vraiment travailler avec une trame de données distincte. Dans ce cas, il est préférable de créer une copie explicite.
discounted_orders = orders[orders["discount"].notna()].copy()
Maintenant discounted_orders est un objet complètement indépendant et sa modification n’affectera pas l’ensemble de données d’origine.
Jusqu’à présent, nous avons vu comment trois comportements peuvent discrètement causer des problèmes :
- incorrect types de données
- inattendu alignement des index
- ambiguë opérations de copie ou d’affichage
Mais il existe une autre habitude qui peut considérablement améliorer la fiabilité de vos flux de données.
C’est une chose à laquelle de nombreux analystes de données pensent rarement : manipulation défensive des données.
Manipulation défensive des données : écrire du code Pandas qui échoue bruyamment
Une chose que j’ai lentement réalisé en travaillant avec des données est que la plupart des problèmes ne viennent pas d’un crash de code.
Ils proviennent d’un code qui s’exécute avec succès mais produit le mauvais numéros.
Et dans Pandas, cela arrive étonnamment souvent car la bibliothèque est conçue pour être flexible. Cela vous empêche rarement de faire quelque chose de douteux.
C’est pourquoi de nombreux ingénieurs de données et analystes expérimentés s’appuient sur quelque chose appelé manipulation défensive des données.
Voici l’idée.
Au lieu de supposer que vos données sont correctes, vous validez vos hypothèses pendant que vous travaillez.
Cela permet de détecter les problèmes plus tôt avant qu’ils ne se propagent discrètement dans votre analyse ou votre pipeline.
Regardons quelques exemples pratiques.
Validez vos types de données
Nous avons vu plus tôt comment revenue La colonne avait l’air numérique mais était en fait stockée sous forme de texte. Une façon d’éviter que cela ne se produise est de vérifier explicitement vos hypothèses.
Par exemple:
assert orders["revenue"].dtype == "int64"
Si le type est incorrect, le code générera immédiatement une erreur.
C’est bien mieux que de découvrir le problème plus tard, lorsque vos mesures ne correspondent pas.
Prévenir les fusions dangereuses
Une autre source courante d’erreurs silencieuses est la fusion d’ensembles de données.
Imaginez que nous ajoutions un petit ensemble de données client :
customers = pd.DataFrame({
"customer_id": [1, 2, 3],
"city": ["Lagos", "Abuja", "Ibadan"]
})
Une fusion typique pourrait ressembler à ceci :
commandes.merge(clients, on=”customer_id”)
Cela fonctionne bien, mais il existe un risque caché.
Si les clés ne sont pas uniques, la fusion pourrait accidentellement créer lignes en doublequi gonfle des mesures telles que le total des revenus.
Pandas fournit une protection très utile pour cela :
orders.merge(customers, on="customer_id", validate="many_to_one")
Désormais, Pandas générera une erreur si la relation entre les ensembles de données n’est pas celle que vous attendez.
Ce petit paramètre peut empêcher un débogage très pénible ultérieurement.
Vérifiez tôt les données manquantes
Les valeurs manquantes peuvent également entraîner un comportement inattendu dans les calculs.
Une vérification de diagnostic rapide peut aider à révéler immédiatement les problèmes :
orders.isna().sum()
Cela montre combien de valeurs manquantes existent dans chaque colonne.
Lorsque les ensembles de données sont volumineux, ces petites vérifications peuvent rapidement révéler des problèmes qui autrement pourraient passer inaperçus.
Un flux de travail défensif simple
Au fil du temps, j’ai commencé à suivre une petite routine chaque fois que je travaille avec un nouvel ensemble de données :
- Inspecter la structure
df.info() - Corriger les types de données
astype() - Vérifier les valeurs manquantes
df.isna().sum() - Valider les fusions
validate="one_to_one" or "many_to_one" - Utiliser
.loclors de la modification des données
Ces étapes ne prennent que quelques secondes, mais elles réduisent considérablement les risques d’introduction de bogues silencieux.
Pensées finales
Lorsque j’ai commencé à apprendre Pandas, la plupart des didacticiels se concentraient sur des opérations puissantes telles que groupby, mergeou pivot_table.
Ces outils sont importants, mais j’ai réalisé que le travail sur des données fiables dépend tout autant de la compréhension comment les pandas se comportent sous le capot.
Des concepts comme :
- types de données
- alignement des index
- comportement de copie ou d’affichage
- manipulation défensive des données
cela ne semble peut-être pas excitant au début, mais ce sont exactement les éléments qui maintiennent les flux de travail de donnéesstable et digne de confiance.
Les plus grosses erreurs dans l’analyse des données proviennent rarement d’un code qui plante.
Ils proviennent d’un code qui fonctionne parfaitement, tout en produisant discrètement de mauvais résultats.
Et comprendre les principes fondamentaux des Pandas est l’un des meilleurs moyens d’éviter cela.
Merci d’avoir lu! Si vous avez trouvé cet article utile, n’hésitez pas à me le faire savoir. J’apprécie vraiment vos commentaires



