Les bases des problèmes de python de débogage

 Les bases des problèmes de python de débogage

Débogage des problèmes de pythonDébogage des problèmes de python
Image de l’auteur | Toile

Avez-vous déjà exécuté un script Python et vous souhaitez immédiatement que vous n’ayez pas appuyé sur Entrée?

Le débogage de la science des données n’est pas seulement un acte; C’est une compétence de survie – en particulier lorsqu’il s’agit de jeux de données désordonnés ou de concevoir des modèles de prédiction sur lesquels les personnes réelles comptent.

Dans cet article, nous explorerons les bases du débogage, en particulier dans vos workflows de science des données, en utilisant un ensemble de données réel à partir d’un travail de livraison Doordash, et surtout, comment déboguer comme un pro.

Prédiction de la durée de la livraison Doordash: à quoi traitons-nous?


Débogage des problèmes de python dans la prédiction de la durée de livraisonDébogage des problèmes de python dans la prédiction de la durée de livraison
Dans ces données projetDoordash a demandé à ses candidats en science des données de prédire la durée de la livraison. Regardons d’abord les informations sur l’ensemble de données. Voici le code:

Voici la sortie:


  Débogage du problème Python pour prédire la durée de la livraison  Débogage du problème Python pour prédire la durée de la livraison

Il semble qu’ils n’aient pas fourni la durée de livraison, vous devez donc le calculer ici. C’est simple, mais pas de soucis si vous êtes un débutant. Voyons comment il peut être calculé.

import pandas as pd
from datetime import datetime

# Assuming historical_data is your DataFrame
historical_data("created_at") = pd.to_datetime(historical_data('created_at'))
historical_data("actual_delivery_time") = pd.to_datetime(historical_data('actual_delivery_time'))
historical_data("actual_total_delivery_duration") = (historical_data("actual_delivery_time") - historical_data("created_at")).dt.total_seconds()
historical_data.head()

Voici la tête de la sortie; vous pouvez voir le actual_total_delivery_duration.


Sortie du débogage du problème Python de la prédiction de la durée de livraisonSortie du débogage du problème Python de la prédiction de la durée de livraison

Bien, maintenant nous pouvons commencer! Mais avant cela, voici le langage de définition des données pour cet ensemble de données.

Colonnes dans historical_data.csv

Caractéristiques du temps:

  • Market_id: une ville / région dans laquelle Doordash opère, par exemple, Los Angeles, donnée dans les données comme identifiant.
  • créé_at: horodatage dans UTC lorsque la commande a été soumise par le consommateur à Doordash. (Remarque: cet horodatage est en UTC, mais au cas où vous en auriez besoin, le fuseau horaire réel de la région était américain / Pacifique).
  • réel_delivery_time: horodatage dans UTC lorsque la commande a été livrée au consommateur.

Caractéristiques du magasin:

  • Store_id: une pièce d’identité représentant le restaurant pour lequel la commande a été soumise.
  • Store_primary_category: Catégorie de cuisine du restaurant, par exemple, italien, asiatique.
  • ORDER_PROTOCOL: Un magasin peut recevoir des commandes de Doordash via de nombreux modes. Ce champ représente un ID indiquant le protocole.

Caractéristiques de commande:

  • Total_items: nombre total d’éléments dans la commande.
  • Sous-total: valeur totale de la commande soumise (en cents).
  • NUM_DISTIND_ITEMS: Nombre d’éléments distincts inclus dans l’ordre.
  • min_item_price: prix de l’article avec le moins de coût de l’ordre (en cents).
  • MAX_ITEM_PRICE: Prix de l’article avec le coût le plus élevé de l’ordre (en cents).

Caractéristiques du marché:

Doordash étant un marché, nous avons des informations sur l’état du marché lorsque la commande est passée, qui peut être utilisée pour estimer le délai de livraison. Les fonctionnalités suivantes sont des valeurs au moment de created_at (Temps de soumission de la commande):

  • TOTAL_ONSHIFT_DASHERS: Nombre de dasters disponibles à moins de 10 miles du magasin au moment de la création de commande.
  • total_busy_dashers: sous-ensemble de ce qui précède total_onshift_dashers qui travaillent actuellement sur une commande.
  • TOTAL_OUTANNIEMS_ORDERS: Nombre de commandes à moins de 10 miles de cette commande qui sont actuellement en cours de traitement.

Prédictions des autres modèles:

Nous avons des prévisions d’autres modèles pour différentes étapes du processus de livraison que nous pouvons utiliser:

  • ESTIMATED_ORDE_PLACE_DURATION: Temps estimé pour que le restaurant reçoive la commande de Doordash (en quelques secondes).
  • ESTIMATED_STORE_TO_CONSUMER_DRIVING_DURANT: Temps de déplacement estimé entre le magasin et le consommateur (en secondes).

Super, alors commençons!

Erreurs de python communes dans les projets de science des données


Erreurs de python communes dans les projets de science des donnéesErreurs de python communes dans les projets de science des données

Dans cette section, nous découvrirons les erreurs de débogage communs dans l’un des Projets de science des donnéesà commencer par la lecture de l’ensemble de données et à passer à la partie la plus importante: la modélisation.

Lire l’ensemble de données: FileNotFoundErrorAvertissement dtype et corrects

Cas 1: fichier introuvable – classique

En science des données, votre premier bug vous salue souvent read_csv. Et pas avec un bonjour. Débogons ce moment exact ensemble, ligne par ligne. Voici le code:

import pandas as pd

try:
    df = pd.read_csv('Strata Questions/historical_data.csv')
    df.head(3)
except FileNotFoundError as e:
    import os
    print("File not found. Here's where Python is looking:")
    print("Working directory:", os.getcwd())
    print("Available files:", os.listdir())
    raise e

Voici la sortie.


Débogage des erreurs de python dans les projets de science des donnéesDébogage des erreurs de python dans les projets de science des données

Vous ne soulevez pas seulement une erreur – vous l’interrogez-vous. Cela montre où le code pense qu’il est et ce qu’il voit autour de lui. Si votre fichier n’est pas sur la liste, vous le savez maintenant. Pas de devinettes. Juste des faits.

Remplacez le chemin par le plein et voilà!

Débogage des erreurs de python dans le fichier introuvablesDébogage des erreurs de python dans le fichier introuvables

Cas 2: DTYPE MISION CONTRÉTATION – Python est silencieusement erroné devine

Vous chargez l’ensemble de données, mais quelque chose est éteint. Le bogue se cache à l’intérieur de vos types.

# Assuming df is your loaded DataFrame
try:
    print("Column Types:n", df.dtypes)
except Exception as e:
    print("Error reading dtypes:", e)

Voici la sortie.


Débogage des erreurs de python dans la mauvaise interprétation DTYPEDébogage des erreurs de python dans la mauvaise interprétation DTYPE

Cas 3: Parsing Date – Le saboteur silencieux

Nous avons découvert que nous devons d’abord calculer la durée de livraison et nous l’avons fait avec cette méthode.

try:
    # This code was shown earlier to calculate the delivery duration
    df("created_at") = pd.to_datetime(df('created_at'))
    df("actual_delivery_time") = pd.to_datetime(df('actual_delivery_time'))
    df("actual_total_delivery_duration") = (df("actual_delivery_time") - df("created_at")).dt.total_seconds()
    print("Successfully calculated delivery duration and checked dtypes.")
    print("Relevant dtypes:n", df(('created_at', 'actual_delivery_time', 'actual_total_delivery_duration')).dtypes)
except Exception as e:
    print("Error during date processing:", e)

Voici la sortie.


Débogage des erreurs de python dans l'analyse de donnéesDébogage des erreurs de python dans l'analyse de données

Bon et professionnel! Maintenant, nous évitons ces erreurs rouges, ce qui soulèvera notre humeur – je sais que les voir peut atténuer votre motivation.

Gestion des données manquantes: KeyErrors, NaNset les pièges logiques


Certains bogues ne plantent pas votre code. Ils vous donnent simplement les mauvais résultats, silencieusement, jusqu’à ce que vous vous demandiez pourquoi votre modèle est des ordures.

Cette section creuse dans les données manquantes – pas juste comment les nettoyer, mais comment les déboguer correctement.

Cas 1: Keyerror – vous pensiez que la colonne existait

Voici notre code.

try:
    print(df('store_rating'))
except KeyError as e:
    print("Column not found:", e)
    print("Here are the available columns:n", df.columns.tolist())

Voici la sortie.


Keyerror dans les problèmes de python de débogageKeyerror dans les problèmes de python de débogage

Le code ne s’est pas cassé à cause de la logique; Il a brisé à cause d’une hypothèse. C’est précisément là que le débogage vit. Énumérez toujours vos colonnes avant d’y accéder aveuglément.

Cas 2: Nan Count – Valeurs manquantes auxquelles vous ne vous attendiez pas

Vous supposez que tout est propre. Mais les données réelles cachent toujours les lacunes. Vérifions-les.

try:
    null_counts = df.isnull().sum()
    print("Nulls per column:n", null_counts(null_counts > 0))
except Exception as e:
    print("Failed to inspect nulls:", e)

Voici la sortie.


Nan compter dans les problèmes de python de débogageNan compter dans les problèmes de python de débogage

Cela expose les fauteurs de troubles silencieux. Peut être store_primary_category manque dans des milliers de lignes. Peut-être que les horodatages ont échoué la conversion et sont maintenant NaT.

Vous ne l’auriez pas connu à moins que vous ne vérifiiez. Débogage – confirmant chaque hypothèse.

Cas 3: Pièges logiques – données manquantes qui ne manquent pas réellement

Disons que vous essayez de filtrer les ordres où le sous-total est supérieur à 1 000 000, attendant des centaines de lignes. Mais cela vous donne zéro:

try:
    filtered = df(df('subtotal') > 1000000)
    print("Rows with subtotal > 1,000,000:", filtered.shape(0))
except Exception as e:
    print("Filtering error:", e)

Ce n’est pas une erreur de code – c’est une erreur logique. Vous vous attendiez à des ordres de grande valeur, mais peut-être aucun n’existe au-dessus de ce seuil. Déboguez-le avec une vérification de la plage:

print("Subtotal range:", df('subtotal').min(), "to", df('subtotal').max())

Voici la sortie.


Pièges logiques dans les problèmes de python de débogagePièges logiques dans les problèmes de python de débogage

Cas 4: isna() ≠ zéro ne signifie pas que c’est propre

Même si isna().sum() Affiche zéro, il peut y avoir des données sales, comme Whitespace ou «Aucun» en tant que chaîne. Exécutez un chèque plus agressif:

try:
    fake_nulls = df(df('store_primary_category').isin(('', ' ', 'None', None)))
    print("Rows with fake missing categories:", fake_nulls.shape(0))
except Exception as e:
    print("Fake missing value check failed:", e)

Cela attrape des poubelles cachées isnull() manques.


Gérer les données manquantes dans les problèmes de python de débogageGérer les données manquantes dans les problèmes de python de débogage

Caractéristiques des problèmes d’ingénierie: TypeErrorsAnalyse de datte, et plus

L’ingénierie des fonctionnalités semble amusante au début, jusqu’à ce que votre nouvelle colonne casse chaque modèle ou lance un TypeError mi-pipeline. Voici comment déboguer cette phase comme quelqu’un qui a été brûlé auparavant.

Cas 1: Vous pensez que vous pouvez diviser, mais vous ne pouvez pas

Créons une nouvelle fonctionnalité. Si une erreur se produit, notre try-except Block l’attrapera.

try:
    df('value_per_item') = df('subtotal') / df('total_items')
    print("value_per_item created successfully")
except Exception as e:
    print("Error occurred:", e)

Voici la sortie.


Caractéristiques des problèmes d'ingénierie dans les problèmes de python de débogageCaractéristiques des problèmes d'ingénierie dans les problèmes de python de débogage

Pas d’erreurs? Bien. Mais regardons de plus près.

print(df(('subtotal', 'total_items', 'value_per_item')).sample(3))

Voici la sortie.


Caractéristiques des problèmes d'ingénierie dans les problèmes de python de débogageCaractéristiques des problèmes d'ingénierie dans les problèmes de python de débogage

Cas 2: La date d’analyse a mal tourné

Maintenant, changez votre dtype est important, mais que se passe-t-il si vous pensez que tout a été fait correctement, mais les problèmes persistent?

# This is the standard way, but it can fail silently on mixed types
df("created_at") = pd.to_datetime(df("created_at"))
df("actual_delivery_time") = pd.to_datetime(df("actual_delivery_time"))

Vous pourriez penser que tout va bien, mais si votre colonne a des types mixtes, il pourrait échouer en silence ou casser votre pipeline. C’est pourquoi, au lieu de faire directement des transformations, il est préférable d’utiliser une fonction robuste.

from datetime import datetime

def parse_date_debug(df, col):
    try:
        parsed = pd.to_datetime(df(col))
        print(f"(SUCCESS) '{col}' parsed successfully.")
        return parsed
    except Exception as e:
        print(f"(ERROR) Failed to parse '{col}':", e)
        # Find non-date-like values to debug
        non_datetimes = df(pd.to_datetime(df(col), errors="coerce").isna())(col).unique()
        print("Sample values causing issue:", non_datetimes(:5))
        raise

df("created_at") = parse_date_debug(df, "created_at")
df("actual_delivery_time") = parse_date_debug(df, "actual_delivery_time")

Voici la sortie.


Mauvaise date analyse dans les problèmes de python de débogageMauvaise date analyse dans les problèmes de python de débogage

Cela vous aide à tracer des lignes défectueuses lorsque DateTime Analyse se bloque.

Cas 3: Division naïve qui pourrait induire en erreur

Cela ne lancera pas une erreur dans notre DataFrame car les colonnes sont déjà numériques. Mais voici le problème: certains ensembles de données se faufilent dans les types d’objets, même lorsqu’ils ressemblent à des chiffres. Cela mène à:

  • Ratios trompeurs
  • Mauvais comportement du modèle
  • Aucune avertissement
df("busy_dashers_ratio") = df("total_busy_dashers") / df("total_onshift_dashers")

Valissons les types avant de calculer, même si l’opération ne lancera pas une erreur.

import numpy as np

def create_ratio_debug(df, num_col, denom_col, new_col):
    num_type = df(num_col).dtype
    denom_type = df(denom_col).dtype

    if not np.issubdtype(num_type, np.number) or not np.issubdtype(denom_type, np.number):
        print(f"(TYPE WARNING) '{num_col}' or '{denom_col}' is not numeric.")
        print(f"{num_col}: {num_type}, {denom_col}: {denom_type}")
        df(new_col) = np.nan
        return df
    
    if (df(denom_col) == 0).any():
        print(f"(DIVISION WARNING) '{denom_col}' contains zeros.")
    
    df(new_col) = df(num_col) / df(denom_col)
    return df

df = create_ratio_debug(df, "total_busy_dashers", "total_onshift_dashers", "busy_dashers_ratio")

Voici la sortie.


Division naïve trompeuse dans les problèmes de python débogueDivision naïve trompeuse dans les problèmes de python débogue

Cela donne une visibilité sur les problèmes potentiels de division par zéro et empêche les bogues silencieux.

Modélisation des erreurs: inadéquation de forme et confusion d’évaluation

Cas 1: les valeurs NAN dans les fonctionnalités provoquent un plan du modèle

Disons que nous voulons construire un modèle de régression linéaire. LinearRegression() ne prend pas en charge les valeurs NAN nativement. Si une ligne dans X a une valeur manquante, le modèle refuse de s’entraîner.

Voici le code, qui crée délibérément un décalage de forme pour déclencher une erreur:

from sklearn.linear_model import LinearRegression

X_train = df(("estimated_order_place_duration", "estimated_store_to_consumer_driving_duration")).iloc(:-10)
y_train = df("actual_total_delivery_duration").iloc(:-5) 
model = LinearRegression()
model.fit(X_train, y_train)

Voici la sortie.


Modélisation des erreurs de débogage des problèmes de pythonModélisation des erreurs de débogage des problèmes de python

Déboglons cette question. Tout d’abord, nous vérifions NANS.

print(X_train.isna().sum())

Voici la sortie.


Débogage des problèmes de python dans les valeurs NANDébogage des problèmes de python dans les valeurs NAN

Bon, vérifions également l’autre variable.

print(y_train.isna().sum())

Voici la sortie.


Débogage des problèmes de python dans les valeurs NANDébogage des problèmes de python dans les valeurs NAN

Les valeurs de décalage et de NAN doivent être résolues. Voici le code pour le réparer.

from sklearn.linear_model import LinearRegression

# Re-align X and y to have the same length
X = df(("estimated_order_place_duration", "estimated_store_to_consumer_driving_duration"))
y = df("actual_total_delivery_duration")

# Step 1: Drop rows with NaN in features (X)
valid_X = X.dropna()

# Step 2: Align y to match the remaining indices of X
y_aligned = y.loc(valid_X.index)

# Step 3: Find indices where y is not NaN
valid_idx = y_aligned.dropna().index

# Step 4: Create final clean datasets
X_clean = valid_X.loc(valid_idx)
y_clean = y_aligned.loc(valid_idx)

model = LinearRegression()
model.fit(X_clean, y_clean)
print("✅ Model trained successfully!")

Et voilà! Voici la sortie.


Ensemble de données de problèmes de python de débogageEnsemble de données de problèmes de python de débogage

Cas 2: Colonnes d’objet (dates) Crasser le modèle

Disons que vous essayez de former un modèle à l’aide d’un horodatage comme actual_delivery_time.

Mais – oh non – c’est toujours un type objet ou DateTime, et vous le mélangez accidentellement avec des colonnes numériques. La régression linéaire n’aime pas cela un peu.

from sklearn.linear_model import LinearRegression

X = df(("actual_delivery_time", "estimated_order_place_duration"))
y = df("actual_total_delivery_duration")

model = LinearRegression()
model.fit(X, y)

Voici le code d’erreur:


Débogage python dans les colonnes d'objetsDébogage python dans les colonnes d'objets

Vous combinez deux types de données incompatibles dans la matrice X:

  • Une colonne (actual_delivery_time) est datetime64.
  • L’autre (estimated_order_place_duration) est int64.

Scikit-Learn s’attend à ce que toutes les fonctionnalités soient la même DTYPE numérique. Il ne peut pas gérer les types mixtes comme DateTime et Int. Résolvons-le en convertissant la colonne DateTime en une représentation numérique (horodatage UNIX).

# Ensure datetime columns are parsed correctly, coercing errors to NaT
df("actual_delivery_time") = pd.to_datetime(df("actual_delivery_time"), errors="coerce")
df("created_at") = pd.to_datetime(df("created_at"), errors="coerce")

# Recalculate duration in case of new NaNs
df("actual_total_delivery_duration") = (df("actual_delivery_time") - df("created_at")).dt.total_seconds()

# Convert datetime to a numeric feature (Unix timestamp in seconds)
df("delivery_time_timestamp") = df("actual_delivery_time").astype("int64") // 10**9

Bien. Maintenant que les DTypes sont numériques, appliquons le modèle ML.

from sklearn.linear_model import LinearRegression

# Use the new numeric timestamp feature
X = df(("delivery_time_timestamp", "estimated_order_place_duration"))
y = df("actual_total_delivery_duration")

# Drop any remaining NaNs from our feature set and target
X_clean = X.dropna()
y_clean = y.loc(X_clean.index).dropna()
X_clean = X_clean.loc(y_clean.index)

model = LinearRegression()
model.fit(X_clean, y_clean)
print("✅ Model trained successfully!")

Voici la sortie.


Débogage python dans les colonnes d'objetsDébogage python dans les colonnes d'objets

Excellent travail!

Réflexions finales: déboguez plus intelligemment, pas plus difficile


Les accidents du modèle ne découlent pas toujours de bogues complexes – parfois, c’est juste une nan errante ou une colonne de date non convertie se faufilant dans votre pipeline de données.

Plutôt que de lutter avec des traces de pile cryptique ou de lancer try-except Des blocs comme les fléchettes dans l’obscurité, creusez dans votre dataframe tôt. Jeter un coup d’œil .info()vérifier .isna().sum()et ne pas hésiter à .dtypes. Ces étapes simples dévoilent les mines terrestres cachées avant même de frapper fit().

Je vous ai montré que même un type d’objet négligé ou une valeur manquante sournoise peut saboter un modèle. Mais avec un œil plus net, une préparation plus propre et une extraction des caractéristiques intentionnelles, vous passez du débogage de manière réactive à la construction intelligente.

Nate Rosidi est un scientifique des données et en stratégie de produit. Il est également professeur auxiliaire qui enseigne l’analyse et est le fondateur de Stratascratch, une plate-forme aidant les scientifiques des données à se préparer à leurs entretiens avec de véritables questions d’entrevue de grandes entreprises. Nate écrit sur les dernières tendances du marché de la carrière, donne des conseils d’entrevue, partage des projets de science des données et couvre tout SQL.



Source link

Related post