Pandas apply / map / applymap
apply, map et applymap sont les trois fonctions principales de Pandas pour la transformation de données. Elles peuvent effectuer des opérations flexibles élément par élément ou par lots sur des DataFrame ou des Series.
Series.map
mapEst une méthode Series, utilisée pour transformer chaque élément d'une Series.
Utilisation de base
Exemple
# Créer une Series
s = pd.Series([1, 2, 3, 4, 5])
print("Données d'origine :")
print(s)
print()
# Utiliser une fonction
print("Chaque élément * 2 :")
print(s.map(lambda x: x * 2))
print()
# Utiliser un mappage de dictionnaire
mapping = {1: "A", 2: "B", 3: "C", 4: "D", 5: "E"}
print("Utilisation du mappage de dictionnaire :")
print(s.map(mapping))
print()
# Utiliser le mappage de Series
mapping_series = pd.Series(["A", "B", "C", "D", "E"], index=[1, 2, 3, 4, 5])
print("Utilisation du mappage de Series :")
print(s.map(mapping_series))
Traitement des valeurs manquantes
Exemple
import numpy as np
s = pd.Series([1, 2, np.nan, 4, 5])
print("Contient NaN :")
print(s)
print()
# map ignore NaN par défaut
print("gestion de map (ignore NaN) :")
print(s.map(lambda x: x * 2 if pd.notna(x) else -1))
DataFrame.applymap
applymapEst une méthode DataFrame qui applique une fonction à chaque élément un par un (Remarque : Pandas 2.0+ recommande d'utiliserDataFrame.mapà la place).
Exemple
import numpy as np
df = pd.DataFrame({
"A": [1, 2, 3],
"B": [4, 5, 6],
"C": [7, 8, 9]
})
print("Données d'origine :")
print(df)
print()
# Multiplier chaque élément par 2
print("Chaque élément * 2 :")
print(df.applymap(lambda x: x * 2))
print()
# Conserver 2 décimales
print("Conserver 2 décimales :")
print(df.applymap(lambda x: round(x, 2)))
applymap effectue des opérations élément par élément et peut être lent pour de grandes données. Si vous n'avez besoin d'opérer que sur des colonnes numériques, envisagez d'utiliser des opérations vectorisées ou apply avec le paramètre axis.
DataFrame.apply
applyEst la méthode la plus flexible et peut appliquer des fonctions le long d'un axe.
Appliquer par colonne
Exemple
import numpy as np
df = pd.DataFrame({
"A": [1, 2, 3, 4, 5],
"B": [10, 20, 30, 40, 50],
"C": [100, 200, 300, 400, 500]
})
print("Données d'origine :")
print(df)
print()
# Par défaut axis=0, appliquer par colonne
print("Somme des colonnes :")
print(df.apply(sum))
print()
print("Maximum des colonnes :")
print(df.apply(max))
Appliquer par ligne
Exemple
import numpy as np
df = pd.DataFrame({
"A": [1, 2, 3],
"B": [10, 20, 30],
"C": [100, 200, 300]
})
print("Données d'origine :")
print(df)
print()
# axis=1, appliquer par ligne
print("Somme des lignes :")
print(df.apply(sum, axis=1))
print()
# Max - min par ligne
print("Étendue des lignes :")
print(df.apply(lambda x: x.max() - x.min(), axis=1))
Utilisation d'aggfunc pour l'agrégation
Exemple
import numpy as np
df = pd.DataFrame({
"A": [1, 2, 3],
"B": [10, 20, 30]
})
# Appliquer plusieurs fonctions à la fois
print("Somme et moyenne simultanément :")
print(df.apply([sum, np.mean]))
print()
# Renvoyer plusieurs valeurs
result = df.apply(lambda x: pd.Series({
"sum": x.sum(),
"mean": x.mean(),
"max": x.max()
}, index=["sum", "mean", "max"]))
print("Renvoi de plusieurs valeurs :")
print(result)
Series.apply
Series peut également utiliser apply, qui est similaire à map mais plus flexible.
Exemple
import numpy as np
s = pd.Series([1, 4, 9, 16, 25])
print("Données d'origine :")
print(s)
print()
# Racine carrée
print("Racine carrée :")
print(s.apply(np.sqrt))
print()
# Retour conditionnel
print("Jugement conditionnel :")
print(s.apply(lambda x: "grand" if x > 10 else "petit"))
Comparaison des performances
Exemple
import numpy as np
import time
# Créer de grandes données
n = 100000
s = pd.Series(np.random.randn(n))
# Tester map vs apply
func = lambda x: x * 2 + 1
start = time.time()
result1 = s.map(func)
map_time = time.time() - start
start = time.time()
result2 = s.apply(func)
apply_time = time.time() - start
# Vectorisé (le plus rapide)
start = time.time()
result3 = s * 2 + 1
vec_time = time.time() - start
print(f"temps de map : {map_time:.4f}s")
print(f"temps d'application : {apply_time:.4f}s")
print(f"temps vectorisé : {vec_time:.4f}s")
print("\nConclusion : privilégiez les opérations vectorisées pour de meilleures performances")
Pratique : Transformation de données
Exemple
import numpy as np
# Créer un DataFrame d'exemple
df = pd.DataFrame({
"Nom": ["Zhang San", "Li Si", "Wang Wu", "Zhao Liu"],
"Âge": [25, 30, 28, 35],
"Salaire": [12000, 15000, 11000, 18000],
"Département": ["Technologie", "Ventes", "Technologie", "Opérations"]
})
print("Données d'origine :")
print(df)
print()
# Utiliser apply pour le calcul au niveau des lignes
def calculate(row):
"""Calcule le revenu annuel et le salaire après impôt"""
annual = row["Salaire"] * 12
tax = annual * 0.1 if annual > 120000 else annual * 0.05
after_tax = annual - tax
return pd.Series({
"Salaire annuel": annual,
"Tax": tax,
"After tax": after_tax
})
result = df.apply(calculate, axis=1)
df_result = pd.concat([df, result], axis=1)
print("Résultats du calcul:")
print(df_result)
Choisir parmi les trois
| Méthode | Objet applicable | Scénario | Performance |
|---|---|---|---|
map |
Séries | Transformation élément par élément, mappage de dictionnaire | Rapide |
applymap |
DataFrame | Transformation élément par élément (colonnes non numériques) | Lent |
apply |
Series/DataFrame | Agrégation ligne/colonne, fonctions personnalisées | Moyenne |
Autres extensionsLorsque des opérations vectorisées (utilisant directement les opérateurs) sont disponibles, n'utilisez pas apply/map ; lorsque map est disponible, n'utilisez pas apply.