Pandas en Python : Structures de Données et Manipulation Avancée

La bibliothèque Pandas est un outil fondamental dans l'écosystème Python pour l'analyse et la manipulation de données. Construite sur NumPy, elle excelle dans le traitement de données textuelles et tabulaires, se positionnant comme le module central pour des tâches telles que l'analyse, le traitement et la visualisation de données.

Pandas offre deux structures de données principales :

  • Les Series : similaires aux tableaux unidimensionnels de NumPy, mais avec des étiquettes d'index.
  • Les DataFrames : des structures tabulaires bidimensionnelles, comparables à des feuilles de calcul ou des tables de bases de données, composées de collections de Series partageant le même index.

Ses capacités s'étendent à :

  1. La lecture et l'écriture de données depuis divers formats (CSV, Excel, SQL, JSON, HDF, etc.).
  2. Des opérations complètes sur des tables uniques : ajout, suppression, modification, interrogation, découpage, application de fonctions d'ordre supérieur, regroupement et agrégation.
  3. La fusion et la jointure de multiples tables de données.
  4. Des fonctions de traçage de base pour la visualisation.
  5. Des outils pour l'analyse statistique élémentaire.

I. La Structure de Données Series

Une Series Pandas est un objet unidimensionnel capable de contenir différents types de données, associé à un index (des étiquettes de données). Elle peut être conceptualisée comme une combinaison d'une liste (ou tableau) et d'un dictionnaire.

import numpy as np
import pandas as pd

# Création d'une Series avec une valeur constante et un index personnalisé
serie_constante = pd.Series(0, index=['pomme', 'banane', 'cerise', 'datte'])
print("Series constante :")
print(serie_constante)
# Résultat :
# pomme     0
# banane    0
# cerise    0
# datte     0
# dtype: int64

print("\nValeurs de la Series :", serie_constante.values)
# [0 0 0 0]
print("Index de la Series :", serie_constante.index)
# Index(['pomme', 'banane', 'cerise', 'datte'], dtype='object')

1.1 Création de Series

Il existe plusieurs manières de construire une Series :

1. À partir d'une simple liste de données :

serie_simple = pd.Series([10, 'texte', 5.25, 70])
print("Series à partir d'une liste :")
print(serie_simple)
# Résultat :
# 0       10
# 1    texte
# 2     5.25
# 3       70
# dtype: object

print("\nIndex :", serie_simple.index)
# RangeIndex(start=0, stop=4, step=1)
print("Valeurs :", serie_simple.values)
# [10 'texte' 5.25 70]

2. Avec un index explicite (étiquettes personnalisées) :

serie_indexee = pd.Series([10, 'texte', 5.25, 70], index=['premiere', 'deuxieme', 'troisieme', 'quatrieme'])
print("Series avec index explicite :")
print(serie_indexee)
print("\nIndex :", serie_indexee.index)
print("Valeurs :", serie_indexee.values)

premiere         10
deuxieme      texte
troisieme      5.25
quatrieme        70
dtype: object
Index(['premiere', 'deuxieme', 'troisieme', 'quatrieme'], dtype='object')
[10 'texte' 5.25 70]

3. À l'aide d'un dictionnaire Python :

donnees_villes = {'Paris': 2141000, 'Lyon': 513000, 'Marseille': 861000, 'Toulouse': 479000}
serie_depuis_dict = pd.Series(donnees_villes)
print("Series à partir d'un dictionnaire :")
print(serie_depuis_dict)

Paris        2141000
Lyon          513000
Marseille     861000
Toulouse      479000
dtype: int64

1.2 Compatibilité des Series avec NumPy (accès par position)

Les Series supportent de nombreuses fonctionnalités de NumPy pour l'indexation et les opérations arithmétiques.

Description Méthode / Opération
Création depuis un tableau NumPy pd.Series(tableau_np)
Opérations avec un scalaire ma_serie * 2
Opérations entre deux Series serie1 + serie2
Indexation par position ma_serie[0], ma_serie[[1, 2, 4]]
Découpage (slicing) ma_serie[0:2]
Fonctions universelles NumPy np.abs(ma_serie)
Filtrage booléen ma_serie[ma_serie > 0]
valeurs_np = np.array([10.0, 20.0, 30.0, 40.0, np.nan])
print("Tableau NumPy :", valeurs_np)
# [10. 20. 30. 40. nan]

serie_numerique = pd.Series(valeurs_np, index=['a', 'b', 'c', 'd', 'e'])
print("\nSeries numérique :")
print(serie_numerique)
# Résultat :
# a    10.0
# b    20.0
# c    30.0
# d    40.0
# e     NaN
# dtype: float64

print("\nSeries au carré :")
print(serie_numerique**2)
# Résultat :
# a     100.0
# b     400.0
# c     900.0
# d    1600.0
# e       NaN
# dtype: float64

print("\nAccès à l'élément d'index 0 :", serie_numerique[0])
print("Accès par étiquette 'a' :", serie_numerique['a'])
print("\nAccès à plusieurs éléments par position :")
print(serie_numerique[[0, 1, 2]])
# a    10.0
# b    20.0
# c    30.0
# dtype: float64

print("\nDécoupage des éléments (0 à 2, exclusif) :")
print(serie_numerique[0:2])
# a    10.0
# b    20.0
# dtype: float64

print("\nApplication de np.sin sur la Series :")
print(np.sin(serie_numerique))
# a    -0.544021
# b     0.912945
# c    -0.988032
# d     0.745113
# e          NaN
# dtype: float64

print("\nFiltrage des éléments > 15 :")
print(serie_numerique[serie_numerique > 15])
# b    20.0
# c    30.0
# d    40.0
# dtype: float64

1.3 Compatibilité des Series avec les Dictionnaires (accès par étiquette)

Les Series se comportent comme des dictionnaires pour l'accès et la vérification d'existence.

Description Méthode / Opération
Création depuis un dictionnaire pd.Series(mon_dict)
Vérification d'existence de clé 'cle' in ma_serie
Indexation par étiquette ma_serie['etiquette'], ma_serie[['etiquette1', 'etiquette2']]
serie_dict_exemple = pd.Series({'prix_cafe': 2.50, 'prix_the': 2.00})
print("Series dictionnaire :")
print(serie_dict_exemple)
# prix_cafe    2.5
# prix_the     2.0
# dtype: float64

print("\n'prix_cafe' est-il dans la Series ?", 'prix_cafe' in serie_dict_exemple)
# True
print("Valeur pour 'prix_the' :", serie_dict_exemple['prix_the'])
# 2.0

1.4 Gestion des Données Manquantes dans une Series

Pandas offre des méthodes dédiées pour traiter les valeurs manquantes (représentées par np.nan).

Méthode Description
dropna() Supprime les lignes (ou éléments) contenant des valeurs NaN.
fillna(valeur) Remplace les valeurs NaN par la valeur spécifiée.
isnull() Retourne un tableau booléen, True pour les NaN.
notnull() Retourne un tableau booléen, True pour les valeurs non NaN.
serie_avec_nan = pd.Series([1.0, 2.0, np.nan, 4.0, np.nan], index=['x', 'y', 'z', 'w', 'v'])
print("Series originale avec NaN :")
print(serie_avec_nan)
# x    1.0
# y    2.0
# z    NaN
# w    4.0
# v    NaN
# dtype: float64

print("\nSeries après dropna() :")
print(serie_avec_nan.dropna())
# x    1.0
# y    2.0
# w    4.0
# dtype: float64

print("\nSeries après fillna(0) :")
print(serie_avec_nan.fillna(0))
# x    1.0
# y    2.0
# z    0.0
# w    4.0
# v    0.0
# dtype: float64

print("\nIndication des valeurs nulles (isnull()) :")
print(serie_avec_nan.isnull())
# x    False
# y    False
# z     True
# w    False
# v     True
# dtype: bool

print("\nIndication des valeurs non nulles (notnull()) :")
print(serie_avec_nan.notnull())
# x     True
# y     True
# z    False
# w     True
# v    False
# dtype: bool

II. La Structure de Données DataFrame

Un DataFrame est une structure de données tabulaire bidimensionnelle, organisée en colonnes et en lignes, chacune ayant un index. On peut le voir comme un ensemble de Series qui partagent le même index.

2.1 Génération d'un tableau de dates : date_range

La fonction pd.date_range est utile pour créer des index basés sur des séquences de dates.

Paramètre Description
start Date de début.
end Date de fin.
periods Nombre de périodes à générer.
freq Fréquence des dates (ex: 'D' pour jour, 'M' pour mois, 'H' pour heure, etc.). Par défaut 'D'.
dates_mensuelles = pd.date_range('2023-01-01', periods=6, freq='M')
print("Index de dates mensuelles :")
print(dates_mensuelles)
# DatetimeIndex(['2023-01-31', '2023-02-28', '2023-03-31', '2023-04-30',
#                '2023-05-31', '2023-06-30'],
#               dtype='datetime64[ns]', freq='M')

np.random.seed(42) # Pour la reproductibilité
donnees_aleatoires = np.random.randn(6, 4) * 5 # Valeurs aléatoires pour le DataFrame
print("\nMatrice de données aléatoires :")
print(donnees_aleatoires)

# Création du DataFrame
cadre_donnees_principal = pd.DataFrame(donnees_aleatoires, index=dates_mensuelles, columns=['Col_A', 'Col_B', 'Col_C', 'Col_D'])
print("\nDataFrame créé :")
print(cadre_donnees_principal)

Col_A Col_B Col_C Col_D
2023-01-31 1.231269 1.442845 0.867373 5.432657
2023-02-28 -0.579477 10.749007 1.839655 -0.082725
2023-03-31 0.621743 0.297615 -0.231571 -0.005510
2023-04-30 0.662883 1.082522 -0.224632 0.316086
2023-05-31 -1.259972 -0.547141 -0.597992 0.639591
2023-06-30 -1.275037 0.627918 -0.076899 -1.579782

III. Attributs d'un DataFrame

Les DataFrames disposent de divers attributs pour inspecter leurs caractéristiques.

Attribut Description
dtypes Affiche les types de données de chaque colonne.
index Permet de voir l'index (étiquettes de lignes).
columns Retourne les étiquettes des colonnes.
values Obtient les données du DataFrame sous forme de tableau NumPy (sans les index ni les en-têtes).
describe() Fournit des statistiques descriptives (min, max, moyenne, écart-type, quartiles) pour les colonnes numériques.
T ou transpose() Transposition du DataFrame (échange lignes et colonnes).
sort_index() Trie le DataFrame par ses index (lignes ou colonnes).
sort_values() Trie le DataFrame selon les valeurs d'une ou plusieurs colonnes.
print("Types de données :")
print(cadre_donnees_principal.dtypes)
# Col_A    float64
# Col_B    float64
# Col_C    float64
# Col_D    float64
# dtype: object

print("\nIndex des lignes :")
print(cadre_donnees_principal.index)
# DatetimeIndex(['2023-01-31', '2023-02-28', '2023-03-31', '2023-04-30',
#                '2023-05-31', '2023-06-30'],
#               dtype='datetime64[ns]', freq='M')

print("\nNoms des colonnes :")
print(cadre_donnees_principal.columns)
# Index(['Col_A', 'Col_B', 'Col_C', 'Col_D'], dtype='object')

print("\nValeurs du DataFrame (tableau NumPy) :")
print(cadre_donnees_principal.values)

print("\nStatistiques descriptives :")
print(cadre_donnees_principal.describe())

Col_A Col_B Col_C Col_D
count 6.000000 6.000000 6.000000 6.000000
mean 0.007801 2.287468 0.287663 0.786066
std 0.916894 3.945890 0.741031 2.105436
min -1.275037 -0.547141 -0.597992 -1.579782
25% -0.989858 0.485348 -0.230337 -0.063421
50% -0.028867 0.855220 -0.150766 0.155288
75% 0.642598 1.342764 0.620268 0.558715
max 1.231269 10.749007 1.839655 5.432657
print("\nDataFrame transposé :")
print(cadre_donnees_principal.T)

2023-01-31 00:00:00 2023-02-28 00:00:00 2023-03-31 00:00:00 2023-04-30 00:00:00 2023-05-31 00:00:00 2023-06-30 00:00:00
Col_A 1.231269 -0.579477 0.621743 0.662883 -1.259972 -1.275037
Col_B 1.442845 10.749007 0.297615 1.082522 -0.547141 0.627918
Col_C 0.867373 1.839655 -0.231571 -0.224632 -0.597992 -0.076899
Col_D 5.432657 -0.082725 -0.005510 0.316086 0.639591 -1.579782
# Trier par index des lignes (par défaut axis=0)
print("\nDataFrame trié par index des lignes :")
print(cadre_donnees_principal.sort_index(axis=0))

# Trier par index des colonnes (axis=1)
print("\nDataFrame trié par index des colonnes :")
print(cadre_donnees_principal.sort_index(axis=1))

# Trier par les valeurs de la colonne 'Col_B'
print("\nDataFrame trié par les valeurs de 'Col_B' :")
print(cadre_donnees_principal.sort_values(by='Col_B'))

Col_A Col_B Col_C Col_D
2023-05-31 -1.259972 -0.547141 -0.597992 0.639591
2023-03-31 0.621743 0.297615 -0.231571 -0.005510
2023-06-30 -1.275037 0.627918 -0.076899 -1.579782
2023-04-30 0.662883 1.082522 -0.224632 0.316086
2023-01-31 1.231269 1.442845 0.867373 5.432657
2023-02-28 -0.579477 10.749007 1.839655 -0.082725

IV. Sélection de Données dans un DataFrame

La sélection de données est une opération cruciale. Voici comment y parvenir avec différentes méthodes.

print("DataFrame actuel :")
print(cadre_donnees_principal)

Col_A Col_B Col_C Col_D
2023-01-31 1.231269 1.442845 0.867373 5.432657
2023-02-28 -0.579477 10.749007 1.839655 -0.082725
2023-03-31 0.621743 0.297615 -0.231571 -0.005510
2023-04-30 0.662883 1.082522 -0.224632 0.316086
2023-05-31 -1.259972 -0.547141 -0.597992 0.639591
2023-06-30 -1.275037 0.627918 -0.076899 -1.579782

4.1 Sélection par noms de colonnes

print("\nSélection de la colonne 'Col_B' :")
print(cadre_donnees_principal['Col_B'])
# 2023-01-31     1.442845
# 2023-02-28    10.749007
# 2023-03-31     0.297615
# 2023-04-30     1.082522
# 2023-05-31    -0.547141
# 2023-06-30     0.627918
# Freq: M, Name: Col_B, dtype: float64

print("\nSélection des colonnes 'Col_A' et 'Col_C' :")
print(cadre_donnees_principal[['Col_A', 'Col_C']])

Col_A Col_C
2023-01-31 1.231269 0.867373
2023-02-28 -0.579477 1.839655
2023-03-31 0.621743 -0.231571
2023-04-30 0.662883 -0.224632
2023-05-31 -1.259972 -0.597992
2023-06-30 -1.275037 -0.076899

4.2 Sélection par étiquettes de lignes (loc)

La méthode .loc[] permet d'accéder aux données en utilisant les étiquettes des lignes et des colonnes.

print("\nSélection de lignes par étiquette d'index (plage incluse) :")
print(cadre_donnees_principal.loc['2023-01-31':'2023-03-31'])

Col_A Col_B Col_C Col_D
2023-01-31 1.231269 1.442845 0.867373 5.432657
2023-02-28 -0.579477 10.749007 1.839655 -0.082725
2023-03-31 0.621743 0.297615 -0.231571 -0.005510

4.3 Sélection par positions entières (iloc)

La méthode .iloc[] fonctionne de manière similaire à l'indexation de tableaux NumPy, en utilisant des positions entières.

print("\nValeur à la ligne 2, colonne 1 (index 0,1) :", cadre_donnees_principal.iloc[2, 1])
# 0.2976154378730419

print("\nSélection par positions entières (lignes 1 à 3, colonnes 1 à 3) :")
print(cadre_donnees_principal.iloc[1:4, 1:4])

Col_B Col_C Col_D
2023-02-28 10.749007 1.839655 -0.082725
2023-03-31 0.297615 -0.231571 -0.005510
2023-04-30 1.082522 -0.224632 0.316086

4.4 Sélection avec des conditions logiques

print("\nLignes où 'Col_A' est supérieure à 0 :")
print(cadre_donnees_principal[cadre_donnees_principal['Col_A'] > 0])

Col_A Col_B Col_C Col_D
2023-01-31 1.231269 1.442845 0.867373 5.432657
2023-03-31 0.621743 0.297615 -0.231571 -0.005510
2023-04-30 0.662883 1.082522 -0.224632 0.316086
print("\nLignes où 'Col_A' est supérieure à 0 ET 'Col_B' est inférieure à 2 :")
print(cadre_donnees_principal[(cadre_donnees_principal['Col_A'] > 0) & (cadre_donnees_principal['Col_B'] < 2)])

Col_A Col_B Col_C Col_D
2023-01-31 1.231269 1.442845 0.867373 5.432657
2023-03-31 0.621743 0.297615 -0.231571 -0.005510
2023-04-30 0.662883 1.082522 -0.224632 0.316086

V. Modification de valeurs dans un DataFrame

Il est simple de modifier les valeurs d'un DataFrame, que ce soit par position, par étiquette, ou par condition.

print("DataFrame avant modification :")
print(cadre_donnees_principal)

Col_A Col_B Col_C Col_D
2023-01-31 1.231269 1.442845 0.867373 5.432657
2023-02-28 -0.579477 10.749007 1.839655 -0.082725
2023-03-31 0.621743 0.297615 -0.231571 -0.005510
2023-04-30 0.662883 1.082522 -0.224632 0.316086
2023-05-31 -1.259972 -0.547141 -0.597992 0.639591
2023-06-30 -1.275037 0.627918 -0.076899 -1.579782
# Modifier les valeurs des deux premières lignes et colonnes à 0
cadre_donnees_principal.iloc[0:2, 0:2] = 0
print("\nDataFrame après modification des premières cellules :")
print(cadre_donnees_principal)

Col_A Col_B Col_C Col_D
2023-01-31 0.000000 0.000000 0.867373 5.432657
2023-02-28 0.000000 0.000000 1.839655 -0.082725
2023-03-31 0.621743 0.297615 -0.231571 -0.005510
2023-04-30 0.662883 1.082522 -0.224632 0.316086
2023-05-31 -1.259972 -0.547141 -0.597992 0.639591
2023-06-30 -1.275037 0.627918 -0.076899 -1.579782
# Appliquer une modification conditionnelle à des lignes entières
# Toutes les lignes où 'Col_C' est supérieure à 1 seront remplacées par une valeur unique (-1)
cadre_donnees_principal[cadre_donnees_principal['Col_C'] > 1] = -1
print("\nDataFrame après modification conditionnelle (lignes entières) :")
print(cadre_donnees_principal)

Col_A Col_B Col_C Col_D
2023-01-31 0.000000 0.000000 0.867373 5.432657
2023-02-28 -1.000000 -1.000000 -1.000000 -1.000000
2023-03-31 0.621743 0.297615 -0.231571 -0.005510
2023-04-30 0.662883 1.082522 -0.224632 0.316086
2023-05-31 -1.259972 -0.547141 -0.597992 0.639591
2023-06-30 -1.275037 0.627918 -0.076899 -1.579782
# Convertir en entier pour l'exemple suivant
cadre_donnees_principal = cadre_donnees_principal.astype(int)
# Remplacer toutes les lignes où 'Col_B' contient -1 par 999
cadre_donnees_principal[cadre_donnees_principal['Col_B'].isin([-1])] = 999
print("\nDataFrame après nouvelle modification conditionnelle :")
print(cadre_donnees_principal)

Col_A Col_B Col_C Col_D
2023-01-31 0 0 0 5
2023-02-28 999 999 999 999
2023-03-31 0 0 0 0
2023-04-30 0 1 0 0
2023-05-31 -1 0 0 0
2023-06-30 -1 0 0 -1

VI. Lecture de fichiers CSV

Les fichiers CSV (Comma Separated Values), TSV (Tab Separated Values) ou TXT sont des formats courants pour les données tabulaires. Pandas facilite leur importation.

Type de fichier Description Méthode Pandas
CSV, TSV, TXT Fichier texte brut avec séparateur (virgule, tabulation, etc.) pd.read_csv
Excel Fichier Microsoft Excel (.xls ou .xlsx) pd.read_excel
SQL Base de données relationnelle pd.read_sql
from io import StringIO

# Exemple de données CSV en chaîne de caractères
donnees_csv_texte = '''val1,val2,val3,val4
1.1,A,true,10
2.2,,false,20
3.3,C,,30
4.4,D,true,
,E,false,50
'''

# Utilisation de StringIO pour simuler un fichier
flux_csv = StringIO(donnees_csv_texte)
df_csv = pd.read_csv(flux_csv)
print("DataFrame lu depuis CSV :")
print(df_csv)

print("\nPremières lignes (head()) :")
print(df_csv.head(2)) # Affiche les 2 premières lignes
print("\nForme du DataFrame (lignes, colonnes) :", df_csv.shape)
print("Noms des colonnes :", df_csv.columns.tolist())
print("Index des lignes :", df_csv.index)
print("Types de données par colonne :")
print(df_csv.dtypes)

val1 val2 val3 val4
0 1.1 A True 10.0
1 2.2 NaN False 20.0
2 3.3 C NaN 30.0
3 4.4 D True NaN
4 NaN E False 50.0

VII. Gestion des Données Manquantes

Les valeurs manquantes sont courantes et nécessitent une attention particulière. Pandas propose plusieurs méthodes pour les identifier et les traiter.

print("Matrice booléenne des valeurs nulles :")
print(df_csv.isnull())

val1 val2 val3 val4
0 False False False False
1 False True False False
2 False False True False
3 False False False True
4 True False False False
# Compter le nombre de valeurs nulles par colonne
print("\nNombre de valeurs nulles par colonne :")
print(df_csv.isnull().sum())
# val1    1
# val2    1
# val3    1
# val4    1
# dtype: int64

# Supprimer les lignes contenant au moins une valeur NaN (axis=0 par défaut)
print("\nDataFrame après suppression des lignes avec NaN :")
print(df_csv.dropna(axis=0))

# Supprimer les colonnes contenant au moins une valeur NaN (axis=1)
print("\nDataFrame après suppression des colonnes avec NaN :")
print(df_csv.dropna(axis=1))

# Supprimer les lignes où TOUTES les valeurs sont NaN
# (Dans cet exemple, il n'y en a pas, donc le DataFrame reste inchangé)
print("\nDataFrame après suppression des lignes entièrement NaN (how='all') :")
print(df_csv.dropna(how='all'))

# Supprimer les lignes qui n'ont pas au moins 3 valeurs non-NaN
print("\nDataFrame après suppression des lignes avec moins de 3 valeurs valides (thresh=3) :")
print(df_csv.dropna(thresh=3))

# Supprimer les lignes où 'val2' est NaN
print("\nDataFrame après suppression des lignes avec NaN dans 'val2' :")
print(df_csv.dropna(subset=['val2']))

# Remplir toutes les valeurs NaN avec une valeur spécifique (ex: 'MANQUANT')
print("\nDataFrame après remplacement des NaN par 'MANQUANT' :")
print(df_csv.fillna(value='MANQUANT'))

VIII. Fusion de Données

Pandas offre des fonctions robustes pour combiner des DataFrames. La fonction pd.concat est la plus flexible.

df_zeros = pd.DataFrame(np.zeros((2, 3)), columns=['X', 'Y', 'Z'])
print("DataFrame 'zeros' :")
print(df_zeros)
#      X    Y    Z
# 0  0.0  0.0  0.0
# 1  0.0  0.0  0.0

df_ones = pd.DataFrame(np.ones((2, 3)), columns=['X', 'Y', 'Z'])
print("\nDataFrame 'ones' :")
print(df_ones)
#      X    Y    Z
# 0  1.0  1.0  1.0
# 1  1.0  1.0  1.0

# Concaténation par ligne (ajout des lignes de df_ones sous df_zeros, axis=0 par défaut)
print("\nConcaténation par ligne :")
print(pd.concat([df_zeros, df_ones], axis=0))
#      X    Y    Z
# 0  0.0  0.0  0.0
# 1  0.0  0.0  0.0
# 0  1.0  1.0  1.0
# 1  1.0  1.0  1.0

# Concaténation par colonne (ajout des colonnes de df_ones à droite de df_zeros)
print("\nConcaténation par colonne :")
print(pd.concat([df_zeros, df_ones], axis=1))
#      X    Y    Z    X    Y    Z
# 0  0.0  0.0  0.0  1.0  1.0  1.0
# 1  0.0  0.0  0.0  1.0  1.0  1.0

# La méthode .append() est une ancienne façon de concaténer par ligne.
# Elle est dépréciée depuis Pandas 1.4.0 et sera retirée dans une future version.
# Il est recommandé d'utiliser pd.concat() à la place.
print("\nUtilisation de .append() (dépréciée, utilisez pd.concat) :")
print(df_zeros._append(df_ones, ignore_index=True)) # ignore_index=True pour réinitialiser l'index
#    X    Y    Z
# 0  0.0  0.0  0.0
# 1  0.0  0.0  0.0
# 2  1.0  1.0  1.0
# 3  1.0  1.0  1.0

IX. Importation et Exportation de Données

Pandas simplifie les opérations d'entrée/sortie de données avec des fonctions read_* et to_*.

9.1 Lecture de fichiers (Importation)

Les fonctions de lecture comme pd.read_csv() ou pd.read_excel() acceptent de nombreux paramètres pour personnaliser l'importation.

Paramètre Description
sep Caractère séparateur (ex: ',', '\t'). Peut être une expression régulière comme '\s+'.
header=None Indique que le fichier n'a pas d'en-tête de colonne.
names Liste des noms de colonnes à attribuer.
index_col Spécifie quelle colonne doit être utilisée comme index du DataFrame.
skiprows Liste des numéros de lignes à ignorer au début du fichier.
na_values Liste de chaînes de caractères à interpréter comme des valeurs manquantes (NaN).
parse_dates Booléen ou liste de colonnes à analyser comme des dates.
# Exemple générique de lecture
# df_import = pd.read_excel("mon_fichier.xlsx")
# df_import = pd.read_csv("mes_donnees.csv", sep=';', header=0)

9.2 Écriture de fichiers (Exportation)

Les méthodes to_csv(), to_excel(), etc., permettent d'exporter des DataFrames.

Paramètre Description
sep Séparateur de champs pour les fichiers texte.
na_rep Chaîne de caractères utilisée pour représenter les valeurs NaN (par défaut vide).
header=False N'écrit pas les noms de colonnes dans le fichier.
index=False N'écrit pas l'index des lignes dans le fichier.
columns Liste des colonnes à inclure dans l'exportation.
# Exemple générique d'écriture
# df_export.to_excel("resultats.xlsx", index=False)
# df_export.to_csv("rapport.csv", sep=',', na_rep='N/A')

X. Lecture de fichiers JSON avec Pandas

Pandas peut directement lire des chaînes JSON ou des fichiers JSON et les convertir en DataFrame, grâce à la fonction pd.read_json().

json_data_str = '''
[
    {"jeu":"loto","numero_tirage":"20230101-100","resultat":"1,5,9,12,18","id_unique":"ABC12345","extra_info":null,"timestamp":1672531200000},
    {"jeu":"loto","numero_tirage":"20230101-101","resultat":"2,6,10,15,20","id_unique":"DEF67890","extra_info":null,"timestamp":1672534800000},
    {"jeu":"kino","numero_tirage":"20230101-102","resultat":"3,7,11,14,22","id_unique":"GHI11223","extra_info":null,"timestamp":1672538400000}
]
'''

df_json_loto = pd.read_json(json_data_str, orient='records')
print("DataFrame lu depuis JSON ('records') :")
print(df_json_loto)

# Exportation vers un fichier Excel
# df_json_loto.to_excel('resultats_json.xlsx',
#                       index=False,
#                       columns=["jeu", "numero_tirage", "resultat", "id_unique", "extra_info", "timestamp"])

jeu numero_tirage resultat id_unique extra_info timestamp
0 loto 20230101-100 1,5,9,12,18 ABC12345 None 1672531200000
1 loto 20230101-101 2,6,10,15,20 DEF67890 None 1672534800000
2 kino 20230101-102 3,7,11,14,22 GHI11223 None 1672538400000

10.1 Les cinq formes du paramètre orient

Le paramètre orient spécifie le format attendu de la chaîne JSON. Il peut prendre l'une des cinq valeurs suivantes :

1. 'split' : format dictionnaire {index -> [index], columns -> [columns], data -> [values]}

Ce format contient explicitement les listes d'index, de colonnes et les données matricielles. Les clés doivent être exactement 'index', 'columns' et 'data'.

json_split_str = '{"index":[10,20,30],"columns":["alpha","beta"],"data":[[100,101],[102,103],[104,105]]}'
df_split = pd.read_json(json_split_str, orient='split')
print("DataFrame avec orient='split' :")
print(df_split)

alpha beta
10 100 101
20 102 103
30 104 105

2. 'records' : format liste de dictionnaires [{column -> value}, ...]

Il s'agit d'une liste où chaque élément est un dictionnaire représentant une ligne du DataFrame, avec les noms de colonnes comme clés et les valeurs correspondantes.

json_records_str = '''
[
    {"id_produit":1, "nom":"Clavier", "prix":75.0},
    {"id_produit":2, "nom":"Souris", "prix":25.0}
]
'''
df_records = pd.read_json(json_records_str, orient='records')
print("\nDataFrame avec orient='records' :")
print(df_records)

id_produit nom prix
0 1 Clavier 75.0
1 2 Souris 25.0

3. 'index' : format dictionnaire {index -> {column -> value}}

Les clés du dictionnaire externe sont les index, et leurs valeurs sont des dictionnaires représentant les lignes (clé: colonne, valeur: donnée).

json_index_str = '{"ID001":{"nom":"Alice","age":30},"ID002":{"nom":"Bob","age":24}}'
df_index = pd.read_json(json_index_str, orient='index')
print("\nDataFrame avec orient='index' :")
print(df_index)

nom age
ID001 Alice 30
ID002 Bob Bob

4. 'columns' : format dictionnaire {column -> {index -> value}}

Les clés du dictionnaire externe sont les noms de colonnes, et leurs valeurs sont des dictionnaires représentant les colonnes (clé: index, valeur: donnée).

json_columns_str = '{"nom":{"R1":"Charlie","R2":"Diana"},"ville":{"R1":"Londres","R2":"Paris"}}'
df_columns = pd.read_json(json_columns_str, orient='columns')
print("\nDataFrame avec orient='columns' :")
print(df_columns)

nom ville
R1 Charlie Londres
R2 Diana Paris

5. 'values' : simplement le tableau de valeurs

C'est une liste de listes, représentant directement les valeurs du DataFrame sans informations d'index ou de colonnes explicites.

json_values_str = '[["fruit","pomme"],["couleur","rouge"]]'
df_values = pd.read_json(json_values_str, orient='values')
print("\nDataFrame avec orient='values' :")
print(df_values)

0 1
0 fruit pomme
1 couleur rouge

XI. Lecture de requêtes SQL avec Pandas

Pandas peut se connecter à des bases de données SQL et exécuter des requêtes pour importer les résultats directement dans un DataFrame via pd.read_sql().

import pymysql # Nécessite 'pip install pymysql'

# Fonction pour se connecter à la base de données et exécuter une requête SQL
def executer_requete_sql(requete):
    connexion = None # Initialiser connexion à None
    try:
        # Configuration de la connexion à MySQL
        connexion = pymysql.connect(
            host="localhost",
            port=3306,
            user="root",
            password="mysecretpassword", # Utilisez un mot de passe sécurisé
            db="ma_base_donnees",
            charset='utf8mb4', # Assurez-vous d'avoir le bon encodage
            cursorclass=pymysql.cursors.DictCursor
        )
        # Lire les données de la base de données directement dans un DataFrame
        data_frame_sql = pd.read_sql(requete, con=connexion)
        return data_frame_sql
    except Exception as e:
        print(f"Erreur lors de l'exécution de la requête SQL : {e}")
        return pd.DataFrame() # Retourne un DataFrame vide en cas d'erreur
    finally:
        if connexion:
            connexion.close() # S'assurer que la connexion est toujours fermée

# Exemple d'utilisation
requete_sql_exemple = "SELECT id, nom, email FROM utilisateurs LIMIT 5" # Votre requête SQL
resultats_db = executer_requete_sql(requete_sql_exemple)

if not resultats_db.empty:
    print("\nNoms des colonnes de la table :", resultats_db.columns.tolist())
    print("\nDonnées lues depuis SQL :")
    print(resultats_db)
else:
    print("\nAucune donnée récupérée ou une erreur s'est produite.")

Étiquettes: Pandas NumPy DataFrame Series Python

Publié le 24 juillet à 03h00