Objectifs
- Créer et charger un DataFrame pandas depuis plusieurs sources (séries, URL, fichier local).
- Inspecter un jeu de données et traiter ses valeurs manquantes.
- Sélectionner, encoder et mettre à l’échelle des features avant modélisation.
- Réduire la dimension d’un jeu de données par PCA.
Le notebook du TP est un modèle à compléter : son code est fourni commenté, à dérouler étape par étape. Les commandes ci-dessous sont celles que le notebook prévoit réellement à chaque étape.
1. Création et chargement d’un DataFrame
# Série pandas (une colonne indexée)
age = pd.Series([23, 22, 25], index=['Student1', 'Student2', 'Student3'])
height = pd.Series([155, 175, 168], index=['Student1', 'Student3', 'Student4'])
# Un DataFrame peut être composé de plusieurs séries
stat = pd.DataFrame({'age': age, 'height': height})
# Depuis une URL (horse-colic : prédire la survie d'un cheval à partir de ses antécédents médicaux)
url = 'https://raw.githubusercontent.com/jbrownlee/Datasets/master/horse-colic.csv'
stat2 = read_csv(url, header=None, na_values='?')
# Depuis un fichier local
stat3 = pd.read_excel('data.xlsx', header=None, na_values='?')
# DataFrame créé directement, avec des valeurs manquantes (np.nan)
x = np.nan
df = pd.DataFrame({
"Type": ['Student1', 'Student2', 'Student3', 'Student4'],
"order": [2, 10, x, 10],
"age": [23, x, 25, 0],
"height": [155, 160, x, 160],
})
2. Obtenir des informations sur un jeu de données
data = pd.read_csv('titanic.csv') # prédire les survivants du naufrage du Titanic
data.shape
data.head()
data.tail()
data.info()
data.describe()
3. Nettoyage des données (data cleaning)
Détection des valeurs manquantes
df.isnull().values.any()
df.isnull().sum()
df.isnull().sum().sum()
df.notnull().values.any()
df.notnull().sum().sum()
df.isna().sum()
df.isna().sum().sum()
df.notna().sum().sum()
Imputation des valeurs manquantes
| Stratégie | Commande | Usage |
|---|---|---|
| Moyenne (mean) | df.fillna(df.mean()) | Remplace les valeurs manquantes par la moyenne de la colonne. |
| Médiane (median) | df.fillna(df.median()) | Préférée quand la distribution de la colonne est asymétrique (skewed). |
| Mode (valeur la plus fréquente) | df['height'] = df['height'].fillna(df['height'].mode()[0]) | Utile pour des champs comme le salaire, quand la donnée est asymétrique. |
4. Sélection de features (feature selection)
# Jeu de données pima-indians-diabetes : prédire si un patient est diabétique
url = "https://raw.githubusercontent.com/jbrownlee/Datasets/master/pima-indians-diabetes.data.csv"
names = ['preg', 'plas', 'pres', 'skin', 'test', 'mass', 'pedi', 'age', 'class']
dataframe = pd.read_csv(url, names=names)
array = dataframe.values
X1 = array[:, 0:8]
Y1 = array[:, 8]
from sklearn.feature_selection import SelectKBest
from sklearn.feature_selection import chi2
# chi2 : stats du chi carré pour des features non négatives, en classification
test = SelectKBest(score_func=chi2, k=4)
fit = test.fit(X1, Y1)
fit.scores_
features = fit.transform(X1)
Les 4 attributs retenus par SelectKBest (scores les plus élevés) : test, plas, age, mass.
5. Transformation des données
Features catégorielles
X1 = pd.DataFrame(
np.array(['M', 'O-', 'medium',
'M', 'O-', 'high',
'F', 'O+', 'high',
'F', 'AB', 'low'])
.reshape((4, 3)))
X1.columns = ['sex', 'blood_type', 'edu_level']
| Type de feature | Encodeur sklearn | Usage |
|---|---|---|
Ordinale (catégories ordonnées, ex. edu_level) | OrdinalEncoder | encoder = OrdinalEncoder(categories=[['low', 'medium', 'high']]) puis X.edu_level = encoder.fit_transform(X.edu_level.values.reshape(-1, 1)), pour respecter l’ordre des catégories. |
| Ordinale, données 1D | LabelEncoder | OrdinalEncoder attend des données 2D (n_samples, n_features), LabelEncoder des données 1D (n_samples,). |
Nominale (ex. sex, blood_type) | OneHotEncoder | onehot = OneHotEncoder(dtype=np.int, sparse=True) puis onehot.fit_transform(X[['sex', 'blood_type']]).toarray(). |
Mise à l’échelle des features (feature scaling)
Le split train/test doit précéder le scaling : sinon la moyenne utilisée pour centrer les données n’est celle ni du train ni du test.
# Standardisation : x_scaled = (x - u) / s, avec u la moyenne et s l'écart-type
from sklearn.preprocessing import StandardScaler
scaler = StandardScaler()
scaler.fit_transform(Y.f3.values.reshape(-1, 1))
# Normalisation (min-max) : x_scaled = (x - min(x)) / (max(x) - min(x))
from sklearn.preprocessing import MinMaxScaler
scaler = MinMaxScaler(feature_range=(0, 1))
df_cars_normalized2 = scaler.fit_transform(df_cars)
| Technique | Formule | Quand l’utiliser |
|---|---|---|
Standardisation (StandardScaler) | (x - u) / s | Distribution gaussienne ; requise par des algorithmes comme les SVM, la régression linéaire/logistique, l’analyse discriminante linéaire. |
Normalisation (MinMaxScaler) | (x - min(x)) / (max(x) - min(x)) | Distribution non gaussienne ou écart-type très faible ; sensible aux outliers. Utile pour k-NN et les réseaux de neurones. |
6. Réduction de dimension (PCA)
Le TP applique une analyse en composantes principales (PCA) de deux façons :
- Calcul manuel : centrage/réduction des données, calcul de la matrice de covariance, calcul des vecteurs et valeurs propres, projection des données initiales sur les nouveaux axes (composantes principales).
- Utilisation de la classe
PCAde scikit-learn : ajustement sur les données, accès aux composantes principales (vecteurs propres) et aux proportions de variance associées (valeurs propres), transformation/projection des données, et tracé du scree plot.
from numpy import array, mean, cov
from numpy.linalg import eig