Skip to content
---
title: "Seaborn Lineplot : guide complet des graphiques en courbes avec sns.lineplot()"
description: "Maîtrisez seaborn lineplot avec des exemples pratiques couvrant plusieurs courbes, les intervalles de confiance, hue, style, les marqueurs, la visualisation de séries temporelles et la personnalisation."
date: 2026-02-11
author: soren
ogImage:
language: en
tag: Seaborn
---
 
# Seaborn Lineplot : guide complet des graphiques en courbes avec sns.lineplot()
 
import BlogHeader from '../../../components/blog-header';
 
<BlogHeader />
 
Les graphiques en courbes sont essentiels pour visualiser des tendances, des séries temporelles et des relations entre variables continues. Pourtant, produire des courbes de qualité “publication” qui communiquent clairement les insights nécessite souvent une configuration matplotlib importante et du style appliqué manuellement. Les data scientists perdent des heures à ajuster les couleurs des lignes, gérer les légendes et formater les axes, alors qu’ils devraient se concentrer sur l’analyse.
 
La fonction `lineplot()` de Seaborn résout ce problème en offrant une interface de haut niveau pour créer de superbes graphiques en courbes avec un minimum de code. Elle gère automatiquement lagrégation statistique, les intervalles de confiance, les palettes de couleurs et le style visuel, tout en restant hautement personnalisable pour des cas dusage avancés.
 
Ce guide couvre tout : des courbes de base aux visualisations avancées multi-séries avec un style personnalisé. Vous apprendrez à créer des graphiques professionnels qui communiquent efficacement les insights de vos données.
 
import BlogSuggestion from '../../../components/blog-suggestion';
 
<BlogSuggestion />
 
## Comprendre les bases de sns.lineplot()
 
La fonction `sns.lineplot()` crée des graphiques en courbes à partir de pandas DataFrames ou de tableaux (arrays). Elle agrège automatiquement les observations multiples pour chaque valeur de x et affiche des intervalles de confiance par défaut.
 
```python copy
import seaborn as sns
import pandas as pd
import matplotlib.pyplot as plt
 
# Create sample data
df = pd.DataFrame({
    'time': range(10),
    'value': [1, 3, 2, 5, 4, 6, 5, 7, 6, 8]
})
 
# Basic lineplot
sns.lineplot(data=df, x='time', y='value')
plt.title('Basic Line Plot')
plt.show()

Cela crée un graphique en courbes épuré avec des libellés d’axes générés automatiquement à partir des noms de colonnes. La fonction gère la mise en forme des données, l’échelle et le style visuel sans configuration manuelle.

Paramètres clés et syntaxe

La fonction sns.lineplot() accepte des données sous plusieurs formats et propose de nombreuses options de personnalisation :

sns.lineplot(
    data=None,      # DataFrame, array, or dict
    x=None,         # Column name or vector for x-axis
    y=None,         # Column name or vector for y-axis
    hue=None,       # Grouping variable for color
    size=None,      # Grouping variable for line width
    style=None,     # Grouping variable for line style
    palette=None,   # Color palette
    markers=False,  # Add markers to data points
    dashes=True,    # Use dashed lines for styles
    ci=95,          # Confidence interval (deprecated in newer versions)
    errorbar=('ci', 95),  # Error representation
    legend='auto',  # Legend display
    ax=None         # Matplotlib axes object
)

Lorsque vous travaillez avec des DataFrames, utiliser des noms de colonnes pour les paramètres x et y rend le code plus lisible :

# Create multi-observation dataset
data = pd.DataFrame({
    'day': [1, 2, 3, 1, 2, 3, 1, 2, 3],
    'sales': [100, 150, 120, 110, 145, 125, 105, 155, 130],
    'store': ['A', 'A', 'A', 'B', 'B', 'B', 'C', 'C', 'C']
})
 
# Plot with automatic aggregation
sns.lineplot(data=data, x='day', y='sales')
plt.title('Average Sales by Day (with 95% CI)')
plt.xlabel('Day of Week')
plt.ylabel('Sales ($)')
plt.show()

La fonction calcule automatiquement la moyenne des ventes par jour et affiche les intervalles de confiance sous forme de bande ombrée autour de la ligne.

Tracer plusieurs courbes avec Hue

Le paramètre hue crée des lignes distinctes pour différents groupes de vos données, en attribuant automatiquement des couleurs différentes :

# Multiple stores on same plot
fig, ax = plt.subplots(figsize=(10, 6))
 
sns.lineplot(
    data=data,
    x='day',
    y='sales',
    hue='store',  # Separate line for each store
    palette='Set2'
)
 
plt.title('Sales Comparison Across Stores')
plt.xlabel('Day of Week')
plt.ylabel('Sales ($)')
plt.legend(title='Store', loc='upper left')
plt.show()

Cela crée trois lignes de couleurs distinctes avec une légende générée automatiquement. Le paramètre palette contrôle le jeu de couleurs.

Pour des scénarios de regroupement plus complexes :

# Multiple grouping variables
customer_data = pd.DataFrame({
    'month': [1, 2, 3, 1, 2, 3, 1, 2, 3, 1, 2, 3],
    'revenue': [5000, 5500, 6000, 4800, 5200, 5800, 6200, 6800, 7200, 6000, 6500, 7000],
    'segment': ['Premium', 'Premium', 'Premium', 'Standard', 'Standard', 'Standard',
                'Premium', 'Premium', 'Premium', 'Standard', 'Standard', 'Standard'],
    'region': ['North', 'North', 'North', 'North', 'North', 'North',
               'South', 'South', 'South', 'South', 'South', 'South']
})
 
# Use hue for segment, style for region
sns.lineplot(
    data=customer_data,
    x='month',
    y='revenue',
    hue='segment',
    style='region',
    markers=True,
    dashes=False
)
 
plt.title('Revenue by Segment and Region')
plt.xlabel('Month')
plt.ylabel('Revenue ($)')
plt.show()

Personnaliser les styles de ligne avec le paramètre Style

Le paramètre style fait varier l’apparence des lignes via différents motifs de tirets ou types de lignes :

# Temperature data with different sensors
temp_data = pd.DataFrame({
    'hour': list(range(24)) * 3,
    'temperature': [15, 14, 13, 12, 12, 13, 15, 17, 19, 21, 23, 24,
                   25, 26, 25, 24, 22, 20, 18, 17, 16, 15, 15, 14] * 3,
    'sensor': ['Sensor_A'] * 24 + ['Sensor_B'] * 24 + ['Sensor_C'] * 24,
    'location': ['Indoor'] * 24 + ['Outdoor'] * 24 + ['Basement'] * 24
})
 
# Add some variation
import numpy as np
np.random.seed(42)
temp_data['temperature'] = temp_data['temperature'] + np.random.normal(0, 1, len(temp_data))
 
fig, ax = plt.subplots(figsize=(12, 6))
 
sns.lineplot(
    data=temp_data,
    x='hour',
    y='temperature',
    hue='location',
    style='location',
    markers=True,
    dashes=True,
    palette='tab10'
)
 
plt.title('24-Hour Temperature Monitoring')
plt.xlabel('Hour of Day')
plt.ylabel('Temperature (°C)')
plt.legend(title='Location')
plt.grid(True, alpha=0.3)
plt.show()

Différents styles de ligne aident à distinguer les groupes lors d’une impression en niveaux de gris ou pour des considérations d’accessibilité.

Ajouter des marqueurs aux points de données

Les marqueurs mettent en évidence des points de données individuels le long de la courbe, utile pour des données clairsemées ou pour souligner des observations spécifiques :

# Quarterly earnings data
earnings = pd.DataFrame({
    'quarter': ['Q1', 'Q2', 'Q3', 'Q4'] * 3,
    'earnings': [2.1, 2.3, 2.5, 2.4, 2.2, 2.4, 2.6, 2.7, 2.3, 2.5, 2.8, 2.9],
    'year': ['2023'] * 4 + ['2024'] * 4 + ['2025'] * 4
})
 
sns.lineplot(
    data=earnings,
    x='quarter',
    y='earnings',
    hue='year',
    markers=True,
    marker='o',  # Specific marker style
    markersize=8,
    linewidth=2.5,
    palette='deep'
)
 
plt.title('Quarterly Earnings per Share')
plt.xlabel('Quarter')
plt.ylabel('EPS ($)')
plt.ylim(2.0, 3.0)
plt.legend(title='Year')
plt.grid(True, alpha=0.3)
plt.show()

Vous pouvez spécifier des styles de marqueurs par groupe :

# Custom markers for different groups
sns.lineplot(
    data=earnings,
    x='quarter',
    y='earnings',
    hue='year',
    style='year',
    markers=['o', 's', '^'],  # Different marker per year
    markersize=10,
    dashes=False
)
 
plt.title('Earnings Trend with Distinct Markers')
plt.show()

Travailler avec les intervalles de confiance et bandes d’erreur

Seaborn calcule automatiquement des intervalles de confiance lorsqu’il existe plusieurs observations pour chaque valeur de x. Cette agrégation statistique aide à communiquer l’incertitude des données :

# Experimental data with replicates
experiment = pd.DataFrame({
    'concentration': [0.1, 0.5, 1.0, 2.0, 5.0] * 10,
    'response': np.random.lognormal(mean=[1, 1.5, 2, 2.5, 3] * 10, sigma=0.3),
    'replicate': list(range(10)) * 5
})
 
fig, axes = plt.subplots(1, 3, figsize=(15, 4))
 
# 95% confidence interval (default)
sns.lineplot(data=experiment, x='concentration', y='response',
             errorbar=('ci', 95), ax=axes[0])
axes[0].set_title('95% Confidence Interval')
 
# Standard deviation
sns.lineplot(data=experiment, x='concentration', y='response',
             errorbar='sd', ax=axes[1])
axes[1].set_title('Standard Deviation')
 
# No error bars
sns.lineplot(data=experiment, x='concentration', y='response',
             errorbar=None, ax=axes[2])
axes[2].set_title('No Error Bars')
 
plt.tight_layout()
plt.show()

Le paramètre errorbar prend en charge plusieurs représentations :

  • ('ci', 95) : intervalle de confiance à 95 %
  • ('pi', 95) : intervalle de prédiction à 95 %
  • 'sd' : écart-type
  • 'se' : erreur standard
  • ('pi', 50) : intervalle interquartile
  • None : aucune représentation de l’erreur

Personnaliser les couleurs avec des palettes

Le paramètre palette contrôle les couleurs des lignes via des palettes nommées ou des listes de couleurs personnalisées :

# Stock price comparison
stocks = pd.DataFrame({
    'date': pd.date_range('2025-01-01', periods=60),
    'price': np.random.randn(60).cumsum() + 100,
    'ticker': ['AAPL'] * 60
})
 
stocks = pd.concat([
    stocks,
    pd.DataFrame({
        'date': pd.date_range('2025-01-01', periods=60),
        'price': np.random.randn(60).cumsum() + 150,
        'ticker': ['GOOGL'] * 60
    }),
    pd.DataFrame({
        'date': pd.date_range('2025-01-01', periods=60),
        'price': np.random.randn(60).cumsum() + 200,
        'ticker': ['MSFT'] * 60
    })
])
 
fig, axes = plt.subplots(2, 2, figsize=(14, 10))
 
# Built-in palette
sns.lineplot(data=stocks, x='date', y='price', hue='ticker',
             palette='Set1', ax=axes[0, 0])
axes[0, 0].set_title('Set1 Palette')
 
# Custom colors
custom_colors = {'AAPL': '#FF6B6B', 'GOOGL': '#4ECDC4', 'MSFT': '#45B7D1'}
sns.lineplot(data=stocks, x='date', y='price', hue='ticker',
             palette=custom_colors, ax=axes[0, 1])
axes[0, 1].set_title('Custom Color Mapping')
 
# Colorblind-safe palette
sns.lineplot(data=stocks, x='date', y='price', hue='ticker',
             palette='colorblind', ax=axes[1, 0])
axes[1, 0].set_title('Colorblind Palette')
 
# Dark palette
sns.lineplot(data=stocks, x='date', y='price', hue='ticker',
             palette='dark', ax=axes[1, 1])
axes[1, 1].set_title('Dark Palette')
 
plt.tight_layout()
plt.show()

Options de palettes populaires :

  • 'deep', 'muted', 'pastel', 'bright', 'dark', 'colorblind'
  • 'Set1', 'Set2', 'Set3', 'Paired', 'tab10'
  • 'viridis', 'plasma', 'inferno', 'magma', 'cividis'

Visualisation de séries temporelles

Seaborn lineplot excelle pour visualiser des séries temporelles avec un formatage automatique des dates :

# Website traffic data
dates = pd.date_range('2025-01-01', periods=180, freq='D')
traffic = pd.DataFrame({
    'date': dates,
    'visits': 1000 + np.random.randn(180).cumsum() * 50 + np.sin(np.arange(180) / 7) * 200,
    'source': ['Organic'] * 180
})
 
# Add paid traffic
paid = pd.DataFrame({
    'date': dates,
    'visits': 500 + np.random.randn(180).cumsum() * 30,
    'source': ['Paid'] * 180
})
 
traffic = pd.concat([traffic, paid])
 
fig, ax = plt.subplots(figsize=(14, 6))
 
sns.lineplot(
    data=traffic,
    x='date',
    y='visits',
    hue='source',
    palette={'Organic': '#2ecc71', 'Paid': '#e74c3c'},
    linewidth=2
)
 
plt.title('Website Traffic Over Time', fontsize=16, fontweight='bold')
plt.xlabel('Date', fontsize=12)
plt.ylabel('Daily Visits', fontsize=12)
plt.legend(title='Traffic Source', title_fontsize=11, fontsize=10)
plt.grid(True, alpha=0.3, linestyle='--')
 
# Format x-axis dates
import matplotlib.dates as mdates
ax.xaxis.set_major_formatter(mdates.DateFormatter('%b %Y'))
ax.xaxis.set_major_locator(mdates.MonthLocator(interval=1))
plt.xticks(rotation=45)
 
plt.tight_layout()
plt.show()

Pour des données avec un index datetime :

# Create time series with datetime index
ts_data = pd.DataFrame({
    'value': np.random.randn(365).cumsum() + 50
}, index=pd.date_range('2025-01-01', periods=365))
 
# Reset index to use in lineplot
ts_data_reset = ts_data.reset_index()
ts_data_reset.columns = ['date', 'value']
 
sns.lineplot(data=ts_data_reset, x='date', y='value')
plt.title('Time Series with Datetime Index')
plt.xticks(rotation=45)
plt.tight_layout()
plt.show()

Tracer plusieurs courbes à partir de données au format wide

Les DataFrames au format wide stockent différentes variables dans des colonnes séparées. Seaborn peut les tracer directement :

# Wide format data
wide_data = pd.DataFrame({
    'month': range(1, 13),
    'Product_A': [100, 120, 115, 130, 140, 135, 150, 160, 155, 170, 180, 175],
    'Product_B': [80, 85, 90, 95, 100, 105, 110, 115, 120, 125, 130, 135],
    'Product_C': [60, 65, 70, 68, 75, 80, 85, 90, 88, 95, 100, 105]
})
 
# Method 1: Melt to long format
long_data = wide_data.melt(id_vars='month', var_name='Product', value_name='Sales')
 
sns.lineplot(data=long_data, x='month', y='Sales', hue='Product')
plt.title('Product Sales Comparison')
plt.xlabel('Month')
plt.ylabel('Sales')
plt.show()

Sinon, tracez directement depuis le format wide :

# Method 2: Plot each column separately
fig, ax = plt.subplots(figsize=(10, 6))
 
for column in ['Product_A', 'Product_B', 'Product_C']:
    sns.lineplot(data=wide_data, x='month', y=column, label=column, ax=ax)
 
plt.title('Product Sales (Wide Format)')
plt.xlabel('Month')
plt.ylabel('Sales')
plt.legend(title='Product')
plt.show()

Combiner avec Matplotlib pour une personnalisation avancée

Seaborn lineplot s’intègre parfaitement à matplotlib pour un contrôle fin :

# Create figure with custom styling
fig, ax = plt.subplots(figsize=(12, 7))
 
# Set overall style
sns.set_style('whitegrid')
sns.set_context('notebook', font_scale=1.2)
 
# Plot data
performance = pd.DataFrame({
    'epoch': list(range(1, 51)) * 2,
    'accuracy': np.concatenate([
        0.6 + 0.008 * np.arange(50) + np.random.randn(50) * 0.02,
        0.55 + 0.009 * np.arange(50) + np.random.randn(50) * 0.025
    ]),
    'model': ['Model_A'] * 50 + ['Model_B'] * 50
})
 
sns.lineplot(
    data=performance,
    x='epoch',
    y='accuracy',
    hue='model',
    palette=['#FF6B6B', '#4ECDC4'],
    linewidth=2.5,
    ax=ax
)
 
# Customize with matplotlib
ax.set_title('Model Training Performance', fontsize=18, fontweight='bold', pad=20)
ax.set_xlabel('Training Epoch', fontsize=14, fontweight='bold')
ax.set_ylabel('Validation Accuracy', fontsize=14, fontweight='bold')
ax.set_ylim(0.5, 1.0)
ax.yaxis.set_major_formatter(plt.FuncFormatter(lambda y, _: f'{y:.0%}'))
 
# Add reference line
ax.axhline(y=0.8, color='gray', linestyle='--', linewidth=1.5, alpha=0.7, label='Target (80%)')
 
# Customize legend
handles, labels = ax.get_legend_handles_labels()
ax.legend(handles, labels, title='Model', title_fontsize=12,
          fontsize=11, loc='lower right', framealpha=0.95)
 
# Add grid customization
ax.grid(True, alpha=0.4, linestyle=':', linewidth=0.8)
ax.set_facecolor('#F8F9FA')
 
# Add annotations
ax.annotate('Model A reaches 90%',
            xy=(45, 0.9), xytext=(35, 0.85),
            arrowprops=dict(arrowstyle='->', color='#FF6B6B', lw=1.5),
            fontsize=10, color='#FF6B6B', fontweight='bold')
 
plt.tight_layout()
plt.show()

Créer des sous-graphiques avec plusieurs lineplots

Comparez différents aspects des données via des mises en page en sous-graphiques :

# Multi-metric dashboard
metrics = pd.DataFrame({
    'time': list(range(100)) * 3,
    'cpu_usage': np.random.rand(300) * 60 + 20 + np.sin(np.arange(300) / 10) * 15,
    'memory_usage': np.random.rand(300) * 40 + 40 + np.cos(np.arange(300) / 15) * 10,
    'disk_io': np.random.rand(300) * 80 + 10 + np.sin(np.arange(300) / 8) * 20,
    'server': ['Server_1'] * 100 + ['Server_2'] * 100 + ['Server_3'] * 100
})
 
fig, axes = plt.subplots(3, 1, figsize=(12, 10), sharex=True)
 
# CPU Usage
sns.lineplot(data=metrics, x='time', y='cpu_usage', hue='server',
             palette='Set2', ax=axes[0], legend=True)
axes[0].set_title('CPU Usage (%)', fontsize=14, fontweight='bold')
axes[0].set_ylabel('Usage (%)')
axes[0].set_xlabel('')
axes[0].axhline(y=80, color='red', linestyle='--', alpha=0.5, label='Threshold')
axes[0].legend(loc='upper left', ncol=4)
 
# Memory Usage
sns.lineplot(data=metrics, x='time', y='memory_usage', hue='server',
             palette='Set2', ax=axes[1], legend=False)
axes[1].set_title('Memory Usage (%)', fontsize=14, fontweight='bold')
axes[1].set_ylabel('Usage (%)')
axes[1].set_xlabel('')
axes[1].axhline(y=80, color='red', linestyle='--', alpha=0.5)
 
# Disk I/O
sns.lineplot(data=metrics, x='time', y='disk_io', hue='server',
             palette='Set2', ax=axes[2], legend=False)
axes[2].set_title('Disk I/O (MB/s)', fontsize=14, fontweight='bold')
axes[2].set_ylabel('Throughput')
axes[2].set_xlabel('Time (seconds)', fontsize=12)
 
plt.tight_layout()
plt.show()

Mises en page en grille pour l’analyse comparative :

# 2x2 comparison grid
fig, axes = plt.subplots(2, 2, figsize=(14, 10))
 
categories = ['Category_A', 'Category_B', 'Category_C', 'Category_D']
positions = [(0, 0), (0, 1), (1, 0), (1, 1)]
 
for category, (i, j) in zip(categories, positions):
    subset = pd.DataFrame({
        'x': range(20),
        'y': np.random.randn(20).cumsum() + 10
    })
 
    sns.lineplot(data=subset, x='x', y='y', ax=axes[i, j],
                marker='o', linewidth=2, color='#3498db')
    axes[i, j].set_title(f'{category} Trend', fontweight='bold')
    axes[i, j].grid(True, alpha=0.3)
 
plt.suptitle('Multi-Category Performance Dashboard', fontsize=16, fontweight='bold', y=1.02)
plt.tight_layout()
plt.show()

Tableau comparatif : sns.lineplot vs plt.plot vs sns.relplot

Featuresns.lineplot()plt.plot()sns.relplot(kind="line")
Automatic aggregationYes (mean + CI)NoYes (mean + CI)
DataFrame integrationNative supportRequires array conversionNative support
Multiple groups (hue)Automatic coloringManual iterationAutomatic coloring
Confidence intervalsBuilt-inManual calculationBuilt-in
FacetGrid supportNo (single axes)NoYes (automatic subplots)
Statistical estimationMean, median, etc.NoneMean, median, etc.
Semantic mappingshue, size, styleManualhue, size, style, col, row
Default stylingSeaborn themeMatplotlib defaultSeaborn theme
Legend handlingAutomaticManualAutomatic
Code complexityLowMediumLow
Performance (large data)MediumFastMedium
Customization depthHigh (via ax)HighestMedium (FacetGrid limits)
Best use caseSingle plot, grouped dataSimple plots, full controlMulti-facet comparisons

Utilisez sns.lineplot() lorsque vous avez besoin d’une agrégation automatique et d’une visualisation statistique sur un seul graphique.

Utilisez plt.plot() lorsque vous avez besoin d’un contrôle maximal, de meilleures performances, ou que vous tracez des données déjà agrégées.

Utilisez sns.relplot(kind="line") lorsque vous avez besoin de graphiques facettés avec génération automatique de sous-graphiques.

Tableau de référence des paramètres

ParameterTypeDefaultDescription
dataDataFrame, dict, arrayNoneInput data structure
x, ystr, arrayNoneVariables for x and y axes
huestrNoneGrouping variable for color encoding
sizestrNoneGrouping variable for line width
stylestrNoneGrouping variable for line dash patterns
palettestr, list, dictNoneColor palette for hue levels
hue_orderlistNoneOrder for hue variable levels
unitsstrNoneGrouping for sampling units (no aggregation)
estimatorfunctionnp.meanAggregation function (mean, median, etc.)
errorbartuple, str('ci', 95)Error representation method
n_bootint1000Bootstrap iterations for CI
seedintNoneRandom seed for bootstrap
sortboolTrueSort x variable before plotting
err_stylestr'band''band' or 'bars' for error display
err_kwsdictNoneKeyword args for error representation
markersbool, listFalseMarker styles for data points
dashesbool, listTrueLine dash patterns
legendstr, bool'auto'Legend display behavior
ciint, 'sd', NoneDeprecatedUse errorbar instead
axAxesNoneMatplotlib axes object
linewidthfloat1.5Width of line
linestylestr'-'Line style ('-', '--', '-.', ':')

Exemple réel : analyse des cours boursiers

# Simulate stock price data
np.random.seed(42)
dates = pd.date_range('2024-01-01', periods=252, freq='B')  # Business days
 
stocks_real = pd.DataFrame({
    'Date': np.tile(dates, 4),
    'Price': np.concatenate([
        100 * np.exp(np.random.randn(252).cumsum() * 0.01),  # AAPL
        150 * np.exp(np.random.randn(252).cumsum() * 0.012), # GOOGL
        200 * np.exp(np.random.randn(252).cumsum() * 0.011), # MSFT
        80 * np.exp(np.random.randn(252).cumsum() * 0.015)   # TSLA
    ]),
    'Ticker': ['AAPL'] * 252 + ['GOOGL'] * 252 + ['MSFT'] * 252 + ['TSLA'] * 252
})
 
# Calculate normalized returns (base = 100)
stocks_normalized = stocks_real.copy()
for ticker in stocks_normalized['Ticker'].unique():
    mask = stocks_normalized['Ticker'] == ticker
    first_price = stocks_normalized.loc[mask, 'Price'].iloc[0]
    stocks_normalized.loc[mask, 'Normalized_Return'] = (
        stocks_normalized.loc[mask, 'Price'] / first_price * 100
    )
 
fig, (ax1, ax2) = plt.subplots(2, 1, figsize=(14, 10))
 
# Absolute prices
sns.lineplot(
    data=stocks_real,
    x='Date',
    y='Price',
    hue='Ticker',
    palette='deep',
    linewidth=2,
    ax=ax1
)
 
ax1.set_title('Stock Prices - Absolute Values (2024)', fontsize=16, fontweight='bold')
ax1.set_xlabel('')
ax1.set_ylabel('Price ($)', fontsize=12)
ax1.legend(title='Ticker', title_fontsize=11, fontsize=10, loc='upper left')
ax1.grid(True, alpha=0.3)
 
# Normalized returns
sns.lineplot(
    data=stocks_normalized,
    x='Date',
    y='Normalized_Return',
    hue='Ticker',
    palette='deep',
    linewidth=2,
    ax=ax2
)
 
ax2.axhline(y=100, color='gray', linestyle='--', linewidth=1, alpha=0.7)
ax2.set_title('Normalized Returns (Base = 100)', fontsize=16, fontweight='bold')
ax2.set_xlabel('Date', fontsize=12)
ax2.set_ylabel('Normalized Return', fontsize=12)
ax2.legend(title='Ticker', title_fontsize=11, fontsize=10, loc='upper left')
ax2.grid(True, alpha=0.3)
 
plt.tight_layout()
plt.show()

Exemple réel : supervision de données de capteurs

# IoT sensor data with noise
hours = np.linspace(0, 24, 288)  # 5-minute intervals
sensor_data = pd.DataFrame({
    'time': np.tile(hours, 4),
    'temperature': np.concatenate([
        20 + 5 * np.sin(hours * np.pi / 12) + np.random.randn(288) * 0.5,  # Room 1
        22 + 4 * np.sin(hours * np.pi / 12 - 0.5) + np.random.randn(288) * 0.7,  # Room 2
        19 + 6 * np.sin(hours * np.pi / 12 + 0.3) + np.random.randn(288) * 0.6,  # Room 3
        21 + 5.5 * np.sin(hours * np.pi / 12 - 0.2) + np.random.randn(288) * 0.8   # Room 4
    ]),
    'room': ['Room_1'] * 288 + ['Room_2'] * 288 + ['Room_3'] * 288 + ['Room_4'] * 288,
    'building': ['Building_A'] * 576 + ['Building_B'] * 576
})
 
fig, ax = plt.subplots(figsize=(14, 7))
 
sns.lineplot(
    data=sensor_data,
    x='time',
    y='temperature',
    hue='room',
    style='building',
    palette='tab10',
    linewidth=2,
    markers=False,
    errorbar=('ci', 68),  # 1 standard deviation
    ax=ax
)
 
# Add comfort zone
ax.axhspan(18, 24, alpha=0.1, color='green', label='Comfort Zone')
 
ax.set_title('24-Hour Temperature Monitoring Across Rooms', fontsize=16, fontweight='bold')
ax.set_xlabel('Hour of Day', fontsize=12)
ax.set_ylabel('Temperature (°C)', fontsize=12)
ax.set_xticks(range(0, 25, 2))
ax.legend(title='Location', bbox_to_anchor=(1.05, 1), loc='upper left')
ax.grid(True, alpha=0.3, linestyle=':')
 
plt.tight_layout()
plt.show()

Exemple réel : résultats d’un test A/B au fil du temps

# A/B test conversion rates over time
days = np.arange(1, 31)
ab_test = pd.DataFrame({
    'day': np.tile(days, 2),
    'conversion_rate': np.concatenate([
        0.05 + 0.001 * days + np.random.randn(30) * 0.005,  # Control
        0.055 + 0.0012 * days + np.random.randn(30) * 0.005  # Variant
    ]) * 100,
    'variant': ['Control'] * 30 + ['Variant_B'] * 30,
    'sample_size': np.random.randint(800, 1200, 60)
})
 
fig, axes = plt.subplots(2, 1, figsize=(12, 9), sharex=True)
 
# Conversion rate trend
sns.lineplot(
    data=ab_test,
    x='day',
    y='conversion_rate',
    hue='variant',
    palette={'Control': '#95a5a6', 'Variant_B': '#27ae60'},
    linewidth=2.5,
    markers=True,
    markersize=6,
    errorbar=None,
    ax=axes[0]
)
 
axes[0].set_title('A/B Test: Conversion Rate Over Time', fontsize=16, fontweight='bold')
axes[0].set_ylabel('Conversion Rate (%)', fontsize=12)
axes[0].set_xlabel('')
axes[0].legend(title='Test Group', fontsize=11)
axes[0].grid(True, alpha=0.3)
 
# Sample size tracking
sns.lineplot(
    data=ab_test,
    x='day',
    y='sample_size',
    hue='variant',
    palette={'Control': '#95a5a6', 'Variant_B': '#27ae60'},
    linewidth=2,
    markers=False,
    errorbar=None,
    ax=axes[1]
)
 
axes[1].set_title('Daily Sample Size', fontsize=14, fontweight='bold')
axes[1].set_ylabel('Users', fontsize=12)
axes[1].set_xlabel('Day of Test', fontsize=12)
axes[1].legend(title='Test Group', fontsize=11)
axes[1].grid(True, alpha=0.3)
 
plt.tight_layout()
plt.show()

Enregistrer et exporter des graphiques en courbes

Enregistrez les graphiques dans différents formats pour des rapports et des présentations :

# Create a polished chart for export
fig, ax = plt.subplots(figsize=(10, 6), dpi=100)
 
export_data = pd.DataFrame({
    'month': ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun'] * 2,
    'revenue': [50, 55, 53, 60, 65, 70, 45, 48, 50, 55, 58, 63],
    'region': ['North'] * 6 + ['South'] * 6
})
 
sns.lineplot(
    data=export_data,
    x='month',
    y='revenue',
    hue='region',
    palette='Set1',
    linewidth=3,
    markers=True,
    markersize=10,
    ax=ax
)
 
ax.set_title('Regional Revenue Comparison', fontsize=16, fontweight='bold', pad=15)
ax.set_xlabel('Month', fontsize=13)
ax.set_ylabel('Revenue ($K)', fontsize=13)
ax.legend(title='Region', title_fontsize=12, fontsize=11)
ax.grid(True, alpha=0.4)
 
# Save in multiple formats
plt.savefig('revenue_comparison.png', dpi=300, bbox_inches='tight')  # High-res PNG
plt.savefig('revenue_comparison.pdf', bbox_inches='tight')           # Vector PDF
plt.savefig('revenue_comparison.svg', bbox_inches='tight')           # SVG for web
 
# Save with transparent background
plt.savefig('revenue_comparison_transparent.png', dpi=300,
            bbox_inches='tight', transparent=True)
 
plt.show()
 
print("Charts saved in multiple formats:")
print("- revenue_comparison.png (300 DPI)")
print("- revenue_comparison.pdf (vector)")
print("- revenue_comparison.svg (web)")
print("- revenue_comparison_transparent.png (transparent)")

Enregistrer avec des dimensions spécifiques :

# Set exact figure size for publication
fig = plt.figure(figsize=(8, 5))  # Width, height in inches
ax = fig.add_subplot(111)
 
sns.lineplot(data=export_data, x='month', y='revenue', hue='region', ax=ax)
ax.set_title('Revenue Trends')
 
# Save with exact pixel dimensions (at 100 DPI: 8 inches * 100 = 800 pixels)
plt.savefig('chart_800x500.png', dpi=100, bbox_inches='tight')
 
# Save with higher resolution (8 inches * 300 DPI = 2400 pixels)
plt.savefig('chart_2400x1500.png', dpi=300, bbox_inches='tight')
 
plt.close()

Graphiques en courbes interactifs avec PyGWalker

Pour l’exploration interactive des données de graphiques en courbes, pensez à PyGWalker, une bibliothèque Python open-source qui convertit les DataFrames en visualisations interactives de type Tableau :

# Install PyGWalker: pip install pygwalker
 
import pygwalker as pyg
import pandas as pd
import numpy as np
 
# Create time series data
dates = pd.date_range('2025-01-01', periods=365, freq='D')
interactive_data = pd.DataFrame({
    'Date': dates,
    'Sales': 1000 + np.random.randn(365).cumsum() * 50,
    'Costs': 600 + np.random.randn(365).cumsum() * 30,
    'Region': np.random.choice(['North', 'South', 'East', 'West'], 365),
    'Product': np.random.choice(['Product_A', 'Product_B', 'Product_C'], 365)
})
 
# Launch interactive explorer
walker = pyg.walk(interactive_data)

PyGWalker fournit :

  • Une interface drag-and-drop pour créer des graphiques en courbes
  • Du filtrage et du regroupement interactifs
  • Une agrégation automatique et un binning des dates
  • La comparaison multi-séries
  • L’export vers des graphiques statiques
  • Pas besoin de coder manuellement chaque visualisation

C’est particulièrement utile en analyse exploratoire (EDA) lorsque vous devez tester rapidement différents regroupements, plages temporelles et agrégations sans écrire du code pour chaque variante. Consultez github.com/Kanaries/pygwalker (opens in a new tab) pour l’installation et la documentation.

Conseils avancés et bonnes pratiques

Gérer les grands jeux de données

Pour des datasets avec des milliers de points par série, envisagez un downsampling ou une agrégation :

# Large dataset simulation
large_data = pd.DataFrame({
    'timestamp': pd.date_range('2025-01-01', periods=10000, freq='T'),
    'value': np.random.randn(10000).cumsum()
})
 
# Method 1: Downsample to hourly
hourly = large_data.set_index('timestamp').resample('H').mean().reset_index()
 
sns.lineplot(data=hourly, x='timestamp', y='value')
plt.title('Downsampled to Hourly Average')
plt.show()
 
# Method 2: Use estimator for automatic aggregation
large_data['hour'] = large_data['timestamp'].dt.floor('H')
 
sns.lineplot(data=large_data, x='hour', y='value', estimator='median')
plt.title('Median Aggregation by Hour')
plt.xticks(rotation=45)
plt.tight_layout()
plt.show()

Combiner plusieurs estimateurs

Comparez différentes agrégations statistiques :

# Noisy experimental data
experiment_multi = pd.DataFrame({
    'dose': [0.1, 0.5, 1.0, 2.0, 5.0] * 20,
    'response': np.random.lognormal([1, 1.5, 2, 2.5, 3] * 20, 0.4)
})
 
fig, axes = plt.subplots(1, 3, figsize=(15, 4))
 
# Mean with CI
sns.lineplot(data=experiment_multi, x='dose', y='response',
             estimator='mean', errorbar=('ci', 95), ax=axes[0])
axes[0].set_title('Mean ± 95% CI')
 
# Median with IQR
sns.lineplot(data=experiment_multi, x='dose', y='response',
             estimator='median', errorbar=('pi', 50), ax=axes[1])
axes[1].set_title('Median ± IQR')
 
# Custom estimator (75th percentile)
sns.lineplot(data=experiment_multi, x='dose', y='response',
             estimator=lambda x: np.percentile(x, 75), errorbar=None, ax=axes[2])
axes[2].set_title('75th Percentile')
 
plt.tight_layout()
plt.show()

Mettre en évidence des zones spécifiques

Attirez l’attention sur des périodes importantes :

# Sales data with promotion period
sales_highlight = pd.DataFrame({
    'week': range(1, 53),
    'sales': 1000 + np.random.randn(52).cumsum() * 100 +
             np.where((np.arange(52) >= 20) & (np.arange(52) <= 30), 500, 0)
})
 
fig, ax = plt.subplots(figsize=(12, 6))
 
sns.lineplot(data=sales_highlight, x='week', y='sales', linewidth=2.5, color='#3498db')
 
# Highlight promotion period
ax.axvspan(20, 30, alpha=0.2, color='gold', label='Promotion Period')
ax.axhline(y=sales_highlight['sales'].mean(), color='red',
           linestyle='--', linewidth=1.5, alpha=0.7, label='Average Sales')
 
ax.set_title('Sales Performance with Promotion Period Highlighted',
             fontsize=16, fontweight='bold')
ax.set_xlabel('Week', fontsize=12)
ax.set_ylabel('Sales ($)', fontsize=12)
ax.legend(fontsize=11)
ax.grid(True, alpha=0.3)
 
plt.tight_layout()
plt.show()

FAQ

Conclusion

La fonction lineplot() de Seaborn fournit une interface puissante et accessible pour créer des graphiques en courbes de qualité publication. De la visualisation de tendances basique aux comparaisons complexes multi-séries avec agrégation statistique, elle prend en charge les tâches courantes de traçage avec un minimum de code tout en conservant une personnalisation complète via l’intégration à matplotlib.

La gestion automatique des intervalles de confiance, le mapping sémantique des couleurs et l’intégration native avec les DataFrames éliminent le code répétitif et vous permettent de vous concentrer sur les insights plutôt que sur la mécanique du plotting. Qu’il s’agisse de visualiser des tendances temporelles, de comparer des groupes expérimentaux ou de surveiller des métriques système, sns.lineplot() produit des visualisations propres et informatives qui communiquent efficacement.

Pour des graphiques statiques destinés à la publication, combinez l’interface haut niveau de seaborn avec le contrôle fin de matplotlib. Pour l’exploration interactive et le prototypage rapide, des outils comme PyGWalker étendent ces capacités via des interfaces drag-and-drop qui ne nécessitent pas de code pour chaque itération de visualisation.

Maîtrisez ces techniques pour transformer des données brutes en récits visuels clairs, qui aident à la prise de décision et à la communication d’insights auprès de publics techniques et non techniques.

📚