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

import pandas as pd

# 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 pandas as pd
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 pandas as pd
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 pandas as pd
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 pandas as pd
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 pandas as pd
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 pandas as pd
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 pandas as pd
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 pandas as pd
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

Lorsque 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.

Autres extensions