Python pour la Data Science : NumPy, Pandas et Scikit-Learn en 2026
Guide pratique de Python pour la data science en 2026. Couverture complète de NumPy pour le calcul vectorisé, Pandas pour le nettoyage et la transformation de données, et Scikit-Learn pour construire des pipelines de machine learning robustes.

Python s'est imposé comme le langage de référence de la data science, non pas par hasard, mais parce que son écosystème de bibliothèques résout des problèmes réels avec une concision remarquable. NumPy, Pandas et Scikit-Learn forment la triade fondamentale que tout data scientist professionnel manipule quotidiennement : NumPy pour le calcul numérique vectorisé, Pandas pour la manipulation et le nettoyage de données tabulaires, Scikit-Learn pour construire, entraîner et déployer des modèles de machine learning. Ce guide parcourt les trois bibliothèques de façon progressive, avec du code directement exécutable, pour aborder les entretiens techniques de 2026 avec une base solide.
Les exemples de ce guide utilisent NumPy 2.0, Pandas 2.2 et Scikit-Learn 1.5, les versions stables en production au premier trimestre 2026. L'installation se fait via pip install numpy pandas scikit-learn ou via un environnement conda. Python 3.11+ est recommandé pour les performances optimales.
NumPy : le calcul vectorisé au coeur de la data science
NumPy est la fondation invisible de l'écosystème data science Python. Pandas, Scikit-Learn et même TensorFlow s'appuient sur ses tableaux multidimensionnels (ndarray) pour effectuer des calculs performants. La différence entre un code Python pur avec des boucles for et du code NumPy peut atteindre un facteur 100 en termes de vitesse d'exécution, grâce à la vectorisation : les opérations s'appliquent à l'ensemble du tableau en une seule instruction, sans itération explicite.
L'exemple suivant illustre les opérations de base : création de tableaux, arithmétique vectorisée, agrégations statistiques et filtrage booléen.
# numpy_basics.py
import numpy as np
# Create arrays from different sources
prices = np.array([29.99, 49.99, 19.99, 99.99, 39.99])
quantities = np.arange(1, 6) # [1, 2, 3, 4, 5]
# Vectorized arithmetic — no loops needed
revenue = prices * quantities
print(revenue) # [29.99, 99.98, 59.97, 399.96, 199.95]
# Statistical aggregations
print(f"Total revenue: ${revenue.sum():.2f}") # $789.85
print(f"Mean price: ${prices.mean():.2f}") # $47.99
print(f"Std deviation: ${prices.std():.2f}") # $27.64
# Boolean indexing — filter without loops
premium_mask = prices > 40
premium_items = prices[premium_mask] # [49.99, 99.99]Le filtrage booléen (prices > 40) produit un tableau de booléens qu'on utilise comme masque pour sélectionner des éléments. Cette syntaxe est omniprésente dans le code data science : elle remplace des boucles conditionnelles verbeuses par une expression lisible et performante. En entretien, expliquer la différence entre indexation par tableau booléen et indexation par indices entiers est une question fréquente.
Reshape et broadcasting : maîtriser les dimensions des tableaux
Deux opérations reviennent systématiquement lors de la préparation de données pour des modèles : le reshaping (changement de forme d'un tableau) et le broadcasting (propagation automatique d'opérations entre tableaux de formes compatibles). Scikit-Learn exige notamment que les données d'entrée soient des tableaux 2D, ce qui nécessite souvent un reshape(-1, 1) pour passer d'un vecteur 1D à une matrice colonne.
# numpy_reshape.py
import numpy as np
# Monthly sales data: 4 products x 3 months
sales = np.array([
[120, 150, 130], # Product A
[200, 180, 220], # Product B
[90, 110, 95], # Product C
[300, 280, 310], # Product D
])
# Column-wise mean (average per month)
monthly_avg = sales.mean(axis=0) # [177.5, 180.0, 188.75]
# Row-wise sum (total per product)
product_totals = sales.sum(axis=1) # [400, 600, 295, 890]
# Normalize each product relative to its own max
normalized = sales / sales.max(axis=1, keepdims=True)
# keepdims=True preserves the shape for broadcasting
print(normalized[0]) # [0.8, 1.0, 0.867] — Product A relative to its peak
# Reshape for Scikit-Learn (requires 2D input)
flat_sales = sales.flatten() # 1D array of 12 values
reshaped = flat_sales.reshape(-1, 1) # 12x1 column vectorL'argument axis contrôle la direction de l'agrégation : axis=0 opère sur les lignes (résultat par colonne), axis=1 opère sur les colonnes (résultat par ligne). Le paramètre keepdims=True est indispensable pour le broadcasting : sans lui, le diviseur perd sa structure matricielle et la division produirait des résultats incorrects. Ces subtilités sont régulièrement testées lors des entretiens techniques en data science.
Pandas : nettoyage et transformation de données réelles
Les données réelles sont rarement propres. Valeurs manquantes, doublons, types incorrects, valeurs aberrantes : chaque jeu de données présente ses propres anomalies. Pandas offre une API expressive pour traiter ces problèmes de manière reproductible. L'approche préconisée en 2026 est le chaînage de méthodes (method chaining) : une seule expression enchaîne toutes les transformations, évitant les variables intermédiaires et facilitant le débogage et la relecture du code.
# pandas_cleaning.py
import pandas as pd
import numpy as np
# Load and inspect raw data
df = pd.read_csv("candidates.csv")
print(df.shape) # (1500, 8)
print(df.dtypes) # Check column types
print(df.isna().sum()) # Count missing values per column
# Clean in a reproducible chain
df_clean = (
df
.dropna(subset=["salary", "experience_years"]) # Drop rows missing critical fields
.assign(
salary=lambda x: x["salary"].clip(lower=20000, upper=500000), # Cap outliers
experience_years=lambda x: x["experience_years"].astype(int),
hired_date=lambda x: pd.to_datetime(x["hired_date"], errors="coerce"),
)
.drop_duplicates(subset=["email"]) # Remove duplicate candidates
.query("experience_years >= 0") # Filter invalid entries
.reset_index(drop=True)
)
print(f"Cleaned: {len(df)} -> {len(df_clean)} rows")L'utilisation de assign avec des fonctions lambda garantit que chaque transformation s'applique à la colonne dans son état courant dans la chaîne, et non à une variable externe qui pourrait avoir été modifiée entre-temps. La méthode clip écrête les valeurs aberrantes sans supprimer les lignes concernées, ce qui préserve le volume de données tout en bornant l'influence des outliers sur les modèles statistiques.
GroupBy et feature engineering avec Pandas
Après le nettoyage, l'étape suivante consiste à créer des variables pertinentes pour le modèle de machine learning. Le groupby de Pandas permet de calculer des statistiques agrégées par groupe, puis de les propager sur tout le DataFrame via transform. Cette technique est au coeur du feature engineering pour les entretiens : enrichir les données individuelles avec un contexte groupé améliore systématiquement la performance des modèles.
# pandas_groupby.py
import pandas as pd
# Aggregate candidate stats by department
dept_stats = (
df_clean
.groupby("department")
.agg(
avg_salary=("salary", "mean"),
median_experience=("experience_years", "median"),
headcount=("email", "count"),
max_salary=("salary", "max"),
)
.sort_values("avg_salary", ascending=False)
)
print(dept_stats.head())
# Create features for ML: encode categorical + add aggregated stats
df_features = (
df_clean
.assign(
# Ratio of individual salary to department average
salary_ratio=lambda x: x["salary"] / x.groupby("department")["salary"].transform("mean"),
# Time since hire in days
tenure_days=lambda x: (pd.Timestamp.now() - x["hired_date"]).dt.days,
# Binary encoding
is_senior=lambda x: (x["experience_years"] >= 5).astype(int),
)
)La variable salary_ratio illustre un pattern particulièrement puissant : diviser la valeur individuelle par la moyenne du groupe produit une variable relative qui capture la position de chaque candidat dans son département, indépendamment des écarts salariaux inter-départements. Ce type de feature améliore systématiquement la performance des modèles de classification sur des données RH ou commerciales. La colonne tenure_days encode l'ancienneté sous forme numérique continue, bien plus exploitable qu'une date brute pour un algorithme de machine learning.
Le DataFrame df_features construit ici sert directement d'entrée aux tâches d'apprentissage supervisé. La qualité du feature engineering détermine souvent davantage la performance finale que le choix de l'algorithme Scikit-Learn lui-même. Un feature engineering soigné avec un modèle simple surpasse fréquemment un modèle complexe appliqué à des données brutes.
Prêt à réussir tes entretiens Data Science & ML ?
Entraîne-toi avec nos simulateurs interactifs, fiches express et tests techniques.
Scikit-Learn : construire un pipeline de machine learning robuste
Scikit-Learn unifie l'interface de tous ses algorithmes sous un contrat commun : fit, predict, transform. Son atout le plus sous-estimé est la classe Pipeline, qui enchaîne preprocessing et modélisation en un objet unique. Cette approche élimine le data leakage — la fuite de statistiques du jeu d'entraînement vers le jeu de test — garantit la reproductibilité et simplifie considérablement le déploiement en production.
Le ColumnTransformer permet d'appliquer des transformations différentes aux colonnes numériques (standardisation) et catégorielles (encodage one-hot) en une seule étape déclarative, sans dupliquer la logique de preprocessing.
# sklearn_pipeline.py
from sklearn.model_selection import train_test_split
from sklearn.pipeline import Pipeline
from sklearn.compose import ColumnTransformer
from sklearn.preprocessing import StandardScaler, OneHotEncoder
from sklearn.ensemble import GradientBoostingClassifier
from sklearn.metrics import classification_report
import pandas as pd
# Define column groups
numeric_features = ["salary", "experience_years", "salary_ratio", "tenure_days"]
categorical_features = ["department", "role_level"]
target = "promoted"
# Split before any preprocessing
X = df_features[numeric_features + categorical_features]
y = df_features[target]
X_train, X_test, y_train, y_test = train_test_split(
X, y, test_size=0.2, random_state=42, stratify=y
)
# Build the preprocessing + model pipeline
preprocessor = ColumnTransformer(
transformers=[
("num", StandardScaler(), numeric_features), # Scale numeric columns
("cat", OneHotEncoder(handle_unknown="ignore"), categorical_features), # Encode categories
]
)
pipeline = Pipeline([
("preprocessor", preprocessor),
("classifier", GradientBoostingClassifier(
n_estimators=200,
learning_rate=0.1,
max_depth=4,
random_state=42,
)),
])
# Train and evaluate
pipeline.fit(X_train, y_train)
y_pred = pipeline.predict(X_test)
print(classification_report(y_test, y_pred))L'argument stratify=y dans train_test_split est crucial sur des classes déséquilibrées : il garantit que la proportion de promotions dans le jeu de test reflète celle de l'ensemble complet. Sans stratification, le jeu de test pourrait contenir proportionnellement beaucoup plus ou moins de cas positifs que le jeu d'entraînement, faussant l'évaluation. Le paramètre handle_unknown="ignore" dans OneHotEncoder protège le pipeline des catégories inconnues à l'inférence, un problème courant en production.
Validation croisée et optimisation des hyperparamètres
L'évaluation d'un modèle sur le même jeu de test pour choisir ses hyperparamètres constitue une forme de data leakage. La validation croisée (cross-validation) résout ce problème en évaluant les performances sur plusieurs sous-ensembles disjoints du jeu d'entraînement. Le GridSearchCV automatise la recherche exhaustive des meilleures combinaisons d'hyperparamètres via validation croisée, et s'applique directement au pipeline complet — preprocessing inclus.
# sklearn_tuning.py
from sklearn.model_selection import cross_val_score, GridSearchCV
import numpy as np
# 5-fold cross-validation on the full pipeline
scores = cross_val_score(pipeline, X_train, y_train, cv=5, scoring="f1")
print(f"F1 scores: {scores}")
print(f"Mean F1: {scores.mean():.3f} (+/- {scores.std() * 2:.3f})")
# Grid search over hyperparameters
param_grid = {
"classifier__n_estimators": [100, 200, 300],
"classifier__max_depth": [3, 4, 5],
"classifier__learning_rate": [0.05, 0.1, 0.2],
}
grid_search = GridSearchCV(
pipeline,
param_grid,
cv=5,
scoring="f1",
n_jobs=-1, # Use all CPU cores
verbose=1,
)
grid_search.fit(X_train, y_train)
print(f"Best params: {grid_search.best_params_}")
print(f"Best F1: {grid_search.best_score_:.3f}")
# Evaluate the best model on held-out test set
best_model = grid_search.best_estimator_
print(classification_report(y_test, best_model.predict(X_test)))La notation classifier__n_estimators (double underscore) est la convention Scikit-Learn pour accéder aux paramètres d'une étape imbriquée dans un pipeline. L'argument n_jobs=-1 parallélise la recherche sur tous les coeurs CPU disponibles, réduisant considérablement le temps d'exécution. Le score F1 est préféré à l'accuracy car le jeu de données de promotions est vraisemblablement déséquilibré — un aspect central des questions d'entretien en machine learning.
Une erreur classique consiste à consulter les scores sur X_test pendant la phase de tuning pour orienter le choix des hyperparamètres. Cela introduit un data leakage indirect : le modèle final devient optimiste car il a, de façon détournée, été sélectionné en fonction des données de test. Le jeu de test doit être utilisé une seule fois, uniquement pour l'évaluation finale du meilleur modèle sélectionné par cross-validation sur le jeu d'entraînement.
Sérialisation et déploiement du pipeline
Un modèle entraîné n'a de valeur que s'il peut être utilisé en production. La bibliothèque joblib sérialise le pipeline complet — preprocessing et modèle — en un seul fichier binaire. Cette approche garantit que les transformations appliquées lors de l'entraînement sont automatiquement reproduites lors de l'inférence, sans aucune duplication de code et sans risque d'inconsistance entre les environnements.
# sklearn_export.py
import joblib
from pathlib import Path
# Save the complete pipeline (preprocessor + model)
model_dir = Path("models")
model_dir.mkdir(exist_ok=True)
joblib.dump(best_model, model_dir / "promotion_model_v1.joblib")
# Load and predict in a different process
loaded_model = joblib.load(model_dir / "promotion_model_v1.joblib")
new_data = pd.DataFrame({
"salary": [75000],
"experience_years": [4],
"salary_ratio": [1.05],
"tenure_days": [730],
"department": ["Engineering"],
"role_level": ["Mid"],
})
prediction = loaded_model.predict(new_data)
probability = loaded_model.predict_proba(new_data)[:, 1]
print(f"Promoted: {bool(prediction[0])}, Confidence: {probability[0]:.2%}")La méthode predict_proba retourne les probabilités de classe, pas seulement la décision binaire. En contexte RH, la confiance du modèle est souvent plus exploitable que la prédiction brute : un score de 62% mérite une revue humaine, là où un score de 94% peut justifier une action automatisée. Cette distinction entre classification dure et probabilité calibrée est une notion essentielle pour les questions d'entretien en data science, notamment lorsque les coûts d'erreur sont asymétriques.
Conclusion
La maîtrise de NumPy, Pandas et Scikit-Learn constitue le socle technique attendu pour tout rôle de data scientist ou ML engineer en 2026. Ces trois bibliothèques couvrent la totalité du cycle de vie d'un projet data : du calcul numérique brut à la mise en production d'un modèle, en passant par le nettoyage et la transformation des données. Les points essentiels à retenir :
- NumPy vectorisation : préférer systématiquement les opérations vectorisées aux boucles Python. Maîtriser
axis,keepdimset le broadcasting pour manipuler des tableaux multidimensionnels sans erreur de dimension. - Pandas method chaining : enchaîner les transformations avec
assign,query,drop_duplicatesetreset_indexproduit un code lisible et reproductible, sans effets de bord entre étapes. - Feature engineering :
groupby+transformest le pattern clé pour enrichir les données individuelles avec des statistiques de groupe. La qualité des features prime généralement sur le choix de l'algorithme. - Scikit-Learn Pipeline : toujours encapsuler preprocessing et modèle dans un
Pipelinecombiné à unColumnTransformerpour éliminer le data leakage et garantir la cohérence entre entraînement et inférence. - Cross-validation : sélectionner les hyperparamètres exclusivement via
cross_val_scoreetGridSearchCVsur le jeu d'entraînement ; utiliserstratifysur les classes déséquilibrées pour des évaluations fiables. - Déploiement :
joblib.dumpsérialise le pipeline complet.predict_probafournit des scores de confiance exploitables, plus utiles que des prédictions binaires dans la plupart des contextes décisionnels.
Passe à la pratique !
Teste tes connaissances avec nos simulateurs d'entretien et tests techniques.
Tags
Partager
Articles similaires

Algorithmes de Machine Learning : Guide Complet pour les Entretiens Techniques
Guide complet des algorithmes de machine learning pour les entretiens techniques. Couvre les modeles lineaires, arbres de decision, methodes d ensemble, clustering, metriques d evaluation et regularisation avec scikit-learn.

Top 25 Questions d'Entretien Data Science en 2026
Questions d'entretien en data science couvrant les statistiques, le machine learning, le feature engineering, le deep learning, SQL et la conception de systèmes — avec des exemples de code Python et des réponses détaillées pour 2026.