Skip to content

Latest commit

 

History

History
1080 lines (835 loc) · 25.4 KB

File metadata and controls

1080 lines (835 loc) · 25.4 KB

🔝 Retour au Sommaire

13.2.1 DataFrames et Series

Introduction à Pandas

Pandas est la bibliothèque incontournable pour la manipulation et l'analyse de données en Python. Son nom vient de "Panel Data" (données de panel) et "Python Data Analysis". Pandas est construite sur NumPy et apporte des structures de données puissantes et intuitives pour travailler avec des données tabulaires.

Installation de Pandas

pip install pandas

Importation conventionnelle

Par convention, Pandas est importé avec l'alias pd :

import pandas as pd  
import numpy as np  # Souvent utilisé avec Pandas  

Les deux structures de données principales

Pandas repose sur deux structures de données fondamentales :

  1. Series : Tableau à une dimension (comme une colonne)
  2. DataFrame : Tableau à deux dimensions (comme une table Excel)
# Visualisation conceptuelle

# Series (1D)
# Index  Valeurs
#   0      10
#   1      20
#   2      30

# DataFrame (2D)
# Index  Nom      Âge    Ville
#   0    Alice    25     Paris
#   1    Bob      30     Lyon
#   2    Charlie  35     Marseille

Les Series

Qu'est-ce qu'une Series ?

Une Series est un array unidimensionnel étiqueté, capable de contenir n'importe quel type de données. C'est similaire à une colonne dans un tableur Excel ou une colonne dans une base de données.

Caractéristiques d'une Series :

  • Peut contenir des entiers, floats, strings, objets Python, etc.
  • Possède un index qui étiquette chaque élément
  • Supporte les opérations vectorisées comme NumPy

Création d'une Series

Méthode 1 : À partir d'une liste

import pandas as pd

# Series simple à partir d'une liste
temperatures = pd.Series([15, 18, 22, 20, 17])  
print(temperatures)  

Sortie :

0    15
1    18
2    22
3    20
4    17
dtype: int64

L'index par défaut est 0, 1, 2, 3, 4...

Méthode 2 : Avec un index personnalisé

# Series avec index personnalisé
temperatures = pd.Series([15, 18, 22, 20, 17],
                         index=['Lundi', 'Mardi', 'Mercredi', 'Jeudi', 'Vendredi'])
print(temperatures)

Sortie :

Lundi        15  
Mardi        18  
Mercredi     22  
Jeudi        20  
Vendredi     17  
dtype: int64  

Méthode 3 : À partir d'un dictionnaire

# Le dictionnaire : clés deviennent l'index, valeurs deviennent les données
villes_population = pd.Series({
    'Paris': 2_161_000,
    'Marseille': 869_000,
    'Lyon': 516_000,
    'Toulouse': 475_000
})
print(villes_population)

Sortie :

Paris         2161000  
Marseille      869000  
Lyon           516000  
Toulouse       475000  
dtype: int64  

Méthode 4 : À partir d'un array NumPy

import numpy as np

# À partir d'un array NumPy
arr = np.array([10, 20, 30, 40, 50])  
serie = pd.Series(arr, index=['a', 'b', 'c', 'd', 'e'])  
print(serie)  

Méthode 5 : Series constante

# Créer une Series avec une valeur constante
serie_constante = pd.Series(100, index=['a', 'b', 'c', 'd'])  
print(serie_constante)  

Sortie :

a    100  
b    100  
c    100  
d    100  
dtype: int64  

Accès aux données d'une Series

temperatures = pd.Series([15, 18, 22, 20, 17],
                         index=['Lundi', 'Mardi', 'Mercredi', 'Jeudi', 'Vendredi'])

# Accès par index de position
print("Premier élément:", temperatures[0])  # 15

# Accès par étiquette
print("Température mardi:", temperatures['Mardi'])  # 18

# Accès multiple
print("Lundi et Vendredi:")  
print(temperatures[['Lundi', 'Vendredi']])  

# Slicing
print("Lundi à Mercredi:")  
print(temperatures['Lundi':'Mercredi'])  # Inclut la fin !  

Propriétés d'une Series

temperatures = pd.Series([15, 18, 22, 20, 17],
                         index=['Lundi', 'Mardi', 'Mercredi', 'Jeudi', 'Vendredi'])

# Valeurs (array NumPy)
print("Valeurs:", temperatures.values)  # [15 18 22 20 17]

# Index
print("Index:", temperatures.index)  # Index(['Lundi', 'Mardi', ...])

# Type de données
print("Type:", temperatures.dtype)  # int64

# Taille
print("Taille:", temperatures.size)  # 5

# Forme
print("Forme:", temperatures.shape)  # (5,)

# Nom de la Series
temperatures.name = "Températures"  
print(temperatures)  

Opérations sur les Series

Opérations arithmétiques

temperatures = pd.Series([15, 18, 22, 20, 17],
                         index=['Lundi', 'Mardi', 'Mercredi', 'Jeudi', 'Vendredi'])

# Addition
print("Températures + 5:")  
print(temperatures + 5)  

# Multiplication
print("Températures × 2:")  
print(temperatures * 2)  

# Conversion Celsius vers Fahrenheit
fahrenheit = temperatures * 9/5 + 32  
print("En Fahrenheit:")  
print(fahrenheit)  

Opérations entre Series

ventes_janvier = pd.Series([100, 150, 200], index=['Produit A', 'Produit B', 'Produit C'])  
ventes_fevrier = pd.Series([120, 140, 210], index=['Produit A', 'Produit B', 'Produit C'])  

# Addition de deux Series
ventes_totales = ventes_janvier + ventes_fevrier  
print("Ventes totales:")  
print(ventes_totales)  

# Différence
evolution = ventes_fevrier - ventes_janvier  
print("Évolution:")  
print(evolution)  

Statistiques descriptives

temperatures = pd.Series([15, 18, 22, 20, 17, 19, 21])

# Statistiques de base
print("Moyenne:", temperatures.mean())  # 18.857...  
print("Médiane:", temperatures.median())  # 19.0  
print("Écart-type:", temperatures.std())  # 2.478...  
print("Minimum:", temperatures.min())  # 15  
print("Maximum:", temperatures.max())  # 22  
print("Somme:", temperatures.sum())  # 132  

# Résumé statistique complet
print(temperatures.describe())

Sortie de describe() :

count     7.000000  
mean     18.857143  
std       2.478232  
min      15.000000  
25%      17.500000
50%      19.000000
75%      20.500000
max      22.000000  
dtype: float64  

Filtrage

temperatures = pd.Series([15, 18, 22, 20, 17],
                         index=['Lundi', 'Mardi', 'Mercredi', 'Jeudi', 'Vendredi'])

# Températures > 18
jours_chauds = temperatures[temperatures > 18]  
print("Jours chauds (>18°C):")  
print(jours_chauds)  

# Températures entre 17 et 20
jours_doux = temperatures[(temperatures >= 17) & (temperatures <= 20)]  
print("Jours doux (17-20°C):")  
print(jours_doux)  

Les DataFrames

Qu'est-ce qu'un DataFrame ?

Un DataFrame est une structure de données bidimensionnelle, similaire à un tableur Excel ou une table SQL. C'est la structure la plus utilisée dans Pandas.

Caractéristiques d'un DataFrame :

  • Tableau 2D avec des lignes et des colonnes
  • Chaque colonne est une Series
  • Peut contenir différents types de données dans différentes colonnes
  • Possède un index pour les lignes et des noms pour les colonnes
# Visualisation d'un DataFrame
#        Nom      Âge    Ville
# 0      Alice    25     Paris
# 1      Bob      30     Lyon
# 2      Charlie  35     Marseille

Création d'un DataFrame

Méthode 1 : À partir d'un dictionnaire de listes

import pandas as pd

# Dictionnaire : clés = noms des colonnes, valeurs = données
donnees = {
    'Nom': ['Alice', 'Bob', 'Charlie', 'David'],
    'Âge': [25, 30, 35, 28],
    'Ville': ['Paris', 'Lyon', 'Marseille', 'Toulouse']
}

df = pd.DataFrame(donnees)  
print(df)  

Sortie :

       Nom  Âge       Ville
0    Alice   25       Paris
1      Bob   30        Lyon
2  Charlie   35  Marseille
3    David   28    Toulouse

Méthode 2 : À partir d'une liste de dictionnaires

# Chaque dictionnaire représente une ligne
etudiants = [
    {'nom': 'Alice', 'note': 15, 'matiere': 'Math'},
    {'nom': 'Bob', 'note': 12, 'matiere': 'Math'},
    {'nom': 'Alice', 'note': 18, 'matiere': 'Physique'}
]

df = pd.DataFrame(etudiants)  
print(df)  

Sortie :

     nom  note   matiere
0  Alice    15      Math
1    Bob    12      Math
2  Alice    18  Physique

Méthode 3 : À partir d'un dictionnaire de Series

# Créer des Series
noms = pd.Series(['Alice', 'Bob', 'Charlie'])  
ages = pd.Series([25, 30, 35])  
villes = pd.Series(['Paris', 'Lyon', 'Marseille'])  

# Créer le DataFrame
df = pd.DataFrame({
    'Nom': noms,
    'Âge': ages,
    'Ville': villes
})
print(df)

Méthode 4 : À partir d'un array NumPy

import numpy as np

# Array 2D
data = np.array([[1, 2, 3],
                 [4, 5, 6],
                 [7, 8, 9]])

df = pd.DataFrame(data,
                  columns=['A', 'B', 'C'],
                  index=['Ligne1', 'Ligne2', 'Ligne3'])
print(df)

Sortie :

        A  B  C
Ligne1  1  2  3  
Ligne2  4  5  6  
Ligne3  7  8  9  

Méthode 5 : À partir d'un fichier CSV

# Lecture d'un fichier CSV (très courant)
# df = pd.read_csv('donnees.csv')

# Exemple de création puis sauvegarde
df = pd.DataFrame({
    'Produit': ['Pomme', 'Banane', 'Orange'],
    'Prix': [2.5, 1.8, 3.2],
    'Stock': [100, 150, 80]
})

# Sauvegarder en CSV
# df.to_csv('produits.csv', index=False)

Index personnalisé

# DataFrame avec index personnalisé
donnees = {
    'Nom': ['Alice', 'Bob', 'Charlie'],
    'Âge': [25, 30, 35],
    'Ville': ['Paris', 'Lyon', 'Marseille']
}

df = pd.DataFrame(donnees, index=['E001', 'E002', 'E003'])  
print(df)  

Sortie :

         Nom  Âge       Ville
E001   Alice   25       Paris  
E002     Bob   30        Lyon  
E003 Charlie   35  Marseille  

Propriétés d'un DataFrame

df = pd.DataFrame({
    'Nom': ['Alice', 'Bob', 'Charlie', 'David'],
    'Âge': [25, 30, 35, 28],
    'Ville': ['Paris', 'Lyon', 'Marseille', 'Toulouse'],
    'Salaire': [35000, 42000, 48000, 38000]
})

# Dimensions (lignes, colonnes)
print("Shape:", df.shape)  # (4, 4)

# Nombre de lignes
print("Nombre de lignes:", len(df))  # 4

# Nombre de colonnes
print("Nombre de colonnes:", len(df.columns))  # 4

# Noms des colonnes
print("Colonnes:", df.columns.tolist())  # ['Nom', 'Âge', 'Ville', 'Salaire']

# Index
print("Index:", df.index.tolist())  # [0, 1, 2, 3]

# Types de données
print("\nTypes de données:")  
print(df.dtypes)  

# Informations générales
print("\nInformations:")  
df.info()  

# Taille (nombre total d'éléments)
print("Taille:", df.size)  # 16 (4 lignes × 4 colonnes)

Sortie de df.dtypes :

Nom         object
Âge          int64
Ville       object  
Salaire      int64  
dtype: object  

Visualisation des données

head() et tail()

df = pd.DataFrame({
    'Jour': ['Lundi', 'Mardi', 'Mercredi', 'Jeudi', 'Vendredi', 'Samedi', 'Dimanche'],
    'Température': [15, 18, 22, 20, 17, 19, 21],
    'Pluie': [0, 0, 5, 2, 0, 0, 1]
})

# Afficher les 5 premières lignes (par défaut)
print("Premières lignes:")  
print(df.head())  

# Afficher les 3 premières lignes
print("\n3 premières lignes:")  
print(df.head(3))  

# Afficher les 5 dernières lignes
print("\nDernières lignes:")  
print(df.tail())  

# Afficher les 2 dernières lignes
print("\n2 dernières lignes:")  
print(df.tail(2))  

Aperçu des données

# Résumé statistique des colonnes numériques
print(df.describe())

# Informations sur les types et valeurs manquantes
df.info()

# Compter les valeurs uniques dans une colonne
print("\nVilles uniques:")  
print(df['Ville'].value_counts())  

Accès aux données

Accès aux colonnes

df = pd.DataFrame({
    'Nom': ['Alice', 'Bob', 'Charlie'],
    'Âge': [25, 30, 35],
    'Ville': ['Paris', 'Lyon', 'Marseille']
})

# Méthode 1 : Notation par crochets (recommandée)
print("Colonne Âge:")  
print(df['Âge'])  

# Méthode 2 : Notation par attribut (si pas d'espace dans le nom)
print("\nColonne Nom:")  
print(df.Nom)  

# Sélectionner plusieurs colonnes
print("\nNom et Ville:")  
print(df[['Nom', 'Ville']])  

Accès aux lignes

Méthode .loc[] - Par étiquette
df = pd.DataFrame({
    'Nom': ['Alice', 'Bob', 'Charlie'],
    'Âge': [25, 30, 35],
    'Ville': ['Paris', 'Lyon', 'Marseille']
}, index=['E001', 'E002', 'E003'])

# Accès à une ligne par son étiquette
print("Ligne E002:")  
print(df.loc['E002'])  

# Accès à plusieurs lignes
print("\nLignes E001 et E003:")  
print(df.loc[['E001', 'E003']])  

# Accès avec slicing (la fin est INCLUSE)
print("\nE001 à E002:")  
print(df.loc['E001':'E002'])  
Méthode .iloc[] - Par position
# Accès à une ligne par sa position (commence à 0)
print("Première ligne (position 0):")  
print(df.iloc[0])  

# Accès à plusieurs lignes
print("\nLignes 0 et 2:")  
print(df.iloc[[0, 2]])  

# Slicing par position (la fin est EXCLUE, comme Python)
print("\nPositions 0 à 2 (exclus):")  
print(df.iloc[0:2])  

Accès à des cellules spécifiques

df = pd.DataFrame({
    'Nom': ['Alice', 'Bob', 'Charlie'],
    'Âge': [25, 30, 35],
    'Ville': ['Paris', 'Lyon', 'Marseille']
})

# .loc[ligne, colonne]
print("Âge de Bob (index 1):")  
print(df.loc[1, 'Âge'])  # 30  

# .iloc[position_ligne, position_colonne]
print("Élément à la position [0, 2]:")  
print(df.iloc[0, 2])  # 'Paris'  

# Accès à un bloc
print("\nLignes 0-1, colonnes Nom et Âge:")  
print(df.loc[0:1, ['Nom', 'Âge']])  

Ajout et modification de données

Ajouter une colonne

df = pd.DataFrame({
    'Nom': ['Alice', 'Bob', 'Charlie'],
    'Âge': [25, 30, 35]
})

# Ajouter une colonne
df['Ville'] = ['Paris', 'Lyon', 'Marseille']  
print(df)  

# Ajouter une colonne calculée
df['Âge_dans_10_ans'] = df['Âge'] + 10  
print(df)  

# Ajouter une colonne avec une valeur constante
df['Pays'] = 'France'  
print(df)  

Modifier des valeurs

df = pd.DataFrame({
    'Nom': ['Alice', 'Bob', 'Charlie'],
    'Âge': [25, 30, 35],
    'Ville': ['Paris', 'Lyon', 'Marseille']
})

# Modifier une cellule
df.loc[0, 'Âge'] = 26  
print(df)  

# Modifier toute une colonne
df['Âge'] = df['Âge'] + 1  
print(df)  

# Modifier plusieurs cellules
df.loc[df['Nom'] == 'Bob', 'Ville'] = 'Nice'  
print(df)  

Ajouter une ligne

df = pd.DataFrame({
    'Nom': ['Alice', 'Bob'],
    'Âge': [25, 30],
    'Ville': ['Paris', 'Lyon']
})

# Créer une nouvelle ligne
nouvelle_ligne = pd.DataFrame({
    'Nom': ['Charlie'],
    'Âge': [35],
    'Ville': ['Marseille']
})

# Ajouter la ligne avec concat
df = pd.concat([df, nouvelle_ligne], ignore_index=True)  
print(df)  

Supprimer des colonnes ou lignes

df = pd.DataFrame({
    'Nom': ['Alice', 'Bob', 'Charlie'],
    'Âge': [25, 30, 35],
    'Ville': ['Paris', 'Lyon', 'Marseille'],
    'Code': ['A1', 'B2', 'C3']
})

# Supprimer une colonne
df_sans_code = df.drop('Code', axis=1)  # axis=1 pour colonnes  
print(df_sans_code)  

# Supprimer plusieurs colonnes
df_reduit = df.drop(['Code', 'Ville'], axis=1)  
print(df_reduit)  

# Supprimer des lignes
df_sans_premiere = df.drop(0, axis=0)  # axis=0 pour lignes  
print(df_sans_premiere)  

# Supprimer avec inplace=True modifie l'original
df.drop('Code', axis=1, inplace=True)  
print(df)  

Filtrage de DataFrames

df = pd.DataFrame({
    'Nom': ['Alice', 'Bob', 'Charlie', 'David', 'Eve'],
    'Âge': [25, 30, 35, 28, 22],
    'Ville': ['Paris', 'Lyon', 'Paris', 'Marseille', 'Lyon'],
    'Salaire': [35000, 42000, 48000, 38000, 32000]
})

# Filtrage simple
personnes_plus_30 = df[df['Âge'] > 30]  
print("Personnes de plus de 30 ans:")  
print(personnes_plus_30)  

# Conditions multiples avec &
parisiens_jeunes = df[(df['Ville'] == 'Paris') & (df['Âge'] < 30)]  
print("\nParisiens de moins de 30 ans:")  
print(parisiens_jeunes)  

# Conditions multiples avec |
lyon_ou_marseille = df[(df['Ville'] == 'Lyon') | (df['Ville'] == 'Marseille')]  
print("\nPersonnes à Lyon ou Marseille:")  
print(lyon_ou_marseille)  

# Utiliser isin() pour plusieurs valeurs
grandes_villes = df[df['Ville'].isin(['Paris', 'Lyon'])]  
print("\nPersonnes dans les grandes villes:")  
print(grandes_villes)  

# Filtrage avec contains (contient une chaîne)
noms_avec_a = df[df['Nom'].str.contains('a', case=False)]  
print("\nNoms contenant 'a':")  
print(noms_avec_a)  

Tri des données

df = pd.DataFrame({
    'Nom': ['Alice', 'Bob', 'Charlie', 'David'],
    'Âge': [25, 30, 35, 28],
    'Ville': ['Paris', 'Lyon', 'Marseille', 'Toulouse'],
    'Salaire': [35000, 42000, 48000, 38000]
})

# Trier par une colonne
df_trie_age = df.sort_values('Âge')  
print("Trié par âge (croissant):")  
print(df_trie_age)  

# Trier en ordre décroissant
df_trie_salaire = df.sort_values('Salaire', ascending=False)  
print("\nTrié par salaire (décroissant):")  
print(df_trie_salaire)  

# Trier par plusieurs colonnes
df_trie_multiple = df.sort_values(['Ville', 'Âge'])  
print("\nTrié par ville puis âge:")  
print(df_trie_multiple)  

# Réinitialiser l'index après le tri
df_trie_reset = df.sort_values('Âge').reset_index(drop=True)  
print("\nTrié avec index réinitialisé:")  
print(df_trie_reset)  

Opérations sur les colonnes

df = pd.DataFrame({
    'Produit': ['Pomme', 'Banane', 'Orange', 'Poire'],
    'Prix_unitaire': [2.5, 1.8, 3.2, 2.8],
    'Quantite': [10, 15, 8, 12]
})

# Créer une nouvelle colonne calculée
df['Total'] = df['Prix_unitaire'] * df['Quantite']  
print(df)  

# Opérations mathématiques sur une colonne
print("\nPrix moyen:", df['Prix_unitaire'].mean())  
print("Prix total:", df['Total'].sum())  
print("Quantité max:", df['Quantite'].max())  

# Appliquer une fonction personnalisée
df['Prix_arrondi'] = df['Prix_unitaire'].round(0)  
print("\nAvec prix arrondi:")  
print(df)  

# Renommer des colonnes
df_renomme = df.rename(columns={
    'Prix_unitaire': 'Prix',
    'Quantite': 'Qté'
})
print("\nColonnes renommées:")  
print(df_renomme)  

Valeurs manquantes

# Créer un DataFrame avec des valeurs manquantes (NaN)
df = pd.DataFrame({
    'Nom': ['Alice', 'Bob', 'Charlie', 'David'],
    'Âge': [25, None, 35, 28],
    'Ville': ['Paris', 'Lyon', None, 'Toulouse'],
    'Salaire': [35000, 42000, 48000, None]
})

print("DataFrame avec valeurs manquantes:")  
print(df)  

# Détecter les valeurs manquantes
print("\nValeurs manquantes (True = manquant):")  
print(df.isnull())  

# Compter les valeurs manquantes par colonne
print("\nNombre de valeurs manquantes:")  
print(df.isnull().sum())  

# Supprimer les lignes avec des valeurs manquantes
df_sans_nan = df.dropna()  
print("\nSans lignes contenant NaN:")  
print(df_sans_nan)  

# Remplir les valeurs manquantes
df_rempli = df.fillna(0)  
print("\nNaN remplacés par 0:")  
print(df_rempli)  

# Remplir avec une valeur spécifique par colonne
df_rempli2 = df.fillna({
    'Âge': df['Âge'].mean(),
    'Ville': 'Inconnu',
    'Salaire': df['Salaire'].median()
})
print("\nNaN remplis avec des valeurs appropriées:")  
print(df_rempli2)  

Opérations par groupe (aperçu)

df = pd.DataFrame({
    'Ville': ['Paris', 'Lyon', 'Paris', 'Lyon', 'Marseille'],
    'Produit': ['A', 'A', 'B', 'B', 'A'],
    'Ventes': [100, 150, 120, 180, 90],
    'Prix': [10, 15, 12, 18, 9]
})

# Moyenne des ventes par ville
moyenne_par_ville = df.groupby('Ville')['Ventes'].mean()  
print("Moyenne des ventes par ville:")  
print(moyenne_par_ville)  

# Somme par produit
somme_par_produit = df.groupby('Produit')['Ventes'].sum()  
print("\nSomme des ventes par produit:")  
print(somme_par_produit)  

# Plusieurs agrégations
stats_par_ville = df.groupby('Ville').agg({
    'Ventes': ['mean', 'sum'],
    'Prix': ['min', 'max']
})
print("\nStatistiques par ville:")  
print(stats_par_ville)  

Exemples pratiques complets

Exemple 1 : Analyse de ventes

# Créer un DataFrame de ventes
ventes = pd.DataFrame({
    'Date': ['2024-01-01', '2024-01-02', '2024-01-03', '2024-01-04', '2024-01-05'],
    'Produit': ['Laptop', 'Souris', 'Clavier', 'Laptop', 'Écran'],
    'Quantite': [2, 10, 5, 1, 3],
    'Prix_unitaire': [800, 25, 60, 800, 250]
})

# Calculer le montant total
ventes['Montant'] = ventes['Quantite'] * ventes['Prix_unitaire']

# Afficher
print("Tableau des ventes:")  
print(ventes)  

# Statistiques
print("\n--- Analyse ---")  
print(f"Revenu total: {ventes['Montant'].sum()}€")  
print(f"Vente moyenne: {ventes['Montant'].mean():.2f}€")  
print(f"Produit le plus vendu: {ventes.loc[ventes['Quantite'].idxmax(), 'Produit']}")  

# Ventes par produit
ventes_par_produit = ventes.groupby('Produit')['Montant'].sum().sort_values(ascending=False)  
print("\nVentes par produit:")  
print(ventes_par_produit)  

Exemple 2 : Carnet d'adresses

# Créer un carnet d'adresses
contacts = pd.DataFrame({
    'Nom': ['Dupont', 'Martin', 'Bernard', 'Thomas'],
    'Prénom': ['Jean', 'Marie', 'Pierre', 'Sophie'],
    'Téléphone': ['0601020304', '0602030405', '0603040506', '0604050607'],
    'Ville': ['Paris', 'Lyon', 'Paris', 'Marseille'],
    'Âge': [35, 28, 42, 31]
})

print("Carnet d'adresses:")  
print(contacts)  

# Créer une colonne nom complet
contacts['Nom_complet'] = contacts['Prénom'] + ' ' + contacts['Nom']

# Filtrer les contacts parisiens
parisiens = contacts[contacts['Ville'] == 'Paris']  
print("\nContacts à Paris:")  
print(parisiens[['Nom_complet', 'Téléphone']])  

# Trier par âge
contacts_tries = contacts.sort_values('Âge')  
print("\nContacts triés par âge:")  
print(contacts_tries[['Nom_complet', 'Âge']])  

Exemple 3 : Notes d'étudiants

# Notes d'étudiants
notes = pd.DataFrame({
    'Étudiant': ['Alice', 'Bob', 'Charlie', 'Diana', 'Eve'],
    'Math': [15, 12, 18, 14, 16],
    'Physique': [13, 14, 16, 15, 12],
    'Chimie': [16, 11, 17, 13, 15],
    'Anglais': [14, 15, 15, 16, 14]
})

print("Tableau des notes:")  
print(notes)  

# Calculer la moyenne de chaque étudiant
notes['Moyenne'] = notes[['Math', 'Physique', 'Chimie', 'Anglais']].mean(axis=1)  
print("\nAvec moyennes:")  
print(notes)  

# Moyenne par matière
print("\nMoyenne de classe par matière:")  
print(notes[['Math', 'Physique', 'Chimie', 'Anglais']].mean())  

# Meilleur étudiant
meilleur = notes.loc[notes['Moyenne'].idxmax()]  
print(f"\nMeilleur étudiant: {meilleur['Étudiant']} avec {meilleur['Moyenne']:.2f}")  

# Étudiants avec moyenne >= 15
mentions = notes[notes['Moyenne'] >= 15]  
print("\nÉtudiants avec mention (≥15):")  
print(mentions[['Étudiant', 'Moyenne']])  

Exemple 4 : Suivi d'activité physique

# Suivi sportif hebdomadaire
activite = pd.DataFrame({
    'Jour': ['Lundi', 'Mardi', 'Mercredi', 'Jeudi', 'Vendredi', 'Samedi', 'Dimanche'],
    'Sport': ['Course', 'Repos', 'Vélo', 'Course', 'Repos', 'Natation', 'Randonnée'],
    'Durée_min': [30, 0, 45, 30, 0, 60, 120],
    'Calories': [300, 0, 400, 300, 0, 500, 600]
})

print("Suivi d'activité:")  
print(activite)  

# Statistiques de la semaine
print("\n--- Statistiques hebdomadaires ---")  
print(f"Temps total d'exercice: {activite['Durée_min'].sum()} minutes")  
print(f"Calories brûlées: {activite['Calories'].sum()} kcal")  
print(f"Durée moyenne par séance: {activite[activite['Durée_min'] > 0]['Durée_min'].mean():.1f} min")  

# Jours actifs
jours_actifs = activite[activite['Durée_min'] > 0]  
print(f"\nNombre de jours actifs: {len(jours_actifs)}")  

# Sport le plus pratiqué (hors repos)
sports_actifs = activite[activite['Sport'] != 'Repos']  
sport_favoris = sports_actifs.groupby('Sport')['Durée_min'].sum().idxmax()  
print(f"Sport le plus pratiqué: {sport_favoris}")  

Bonnes pratiques

1. Nommer clairement les DataFrames et colonnes

# ❌ Moins bon
df = pd.DataFrame({'a': [1, 2], 'b': [3, 4]})

# ✅ Mieux
ventes = pd.DataFrame({'produit': [1, 2], 'quantite': [3, 4]})

2. Vérifier les données après import

# Toujours vérifier après avoir chargé des données
# df = pd.read_csv('data.csv')
# print(df.head())
# print(df.info())
# print(df.describe())

3. Utiliser des copies pour éviter les modifications involontaires

# Si vous voulez modifier sans affecter l'original
df_original = pd.DataFrame({'A': [1, 2, 3]})  
df_copie = df_original.copy()  
df_copie['A'] = df_copie['A'] * 2  # N'affecte pas df_original  

4. Chaîner les opérations pour plus de lisibilité

# Au lieu de :
df_filtre = df[df['Âge'] > 25]  
df_trie = df_filtre.sort_values('Salaire')  
resultat = df_trie[['Nom', 'Salaire']]  

# On peut faire :
resultat = (df[df['Âge'] > 25]
            .sort_values('Salaire')
            [['Nom', 'Salaire']])

5. Attention aux SettingWithCopyWarning

# ❌ Peut causer des problèmes
# df[df['A'] > 0]['B'] = 5  # Warning !

# ✅ Utiliser .loc[]
# df.loc[df['A'] > 0, 'B'] = 5

Résumé

Dans cette section, nous avons exploré les deux structures de données fondamentales de Pandas :

Series

  • Tableau unidimensionnel étiqueté
  • Similaire à une colonne
  • Supporte les opérations vectorisées
  • Possède un index

DataFrames

  • Tableau bidimensionnel (lignes et colonnes)
  • Similaire à une table Excel ou SQL
  • Chaque colonne est une Series
  • Permet des manipulations puissantes de données

Opérations clés apprises :

  • Création de Series et DataFrames
  • Accès aux données (.loc, .iloc, [])
  • Ajout et modification de colonnes/lignes
  • Filtrage et tri
  • Statistiques descriptives
  • Gestion des valeurs manquantes

Ces concepts constituent la base de l'analyse de données avec Pandas. Dans les sections suivantes, nous approfondirons le nettoyage et la transformation de données, ainsi que les opérations de regroupement plus avancées.

⏭️ Nettoyage et transformation de données