Avancé

Interactivité Plotly dans Streamlit

Au-delà du hover et du zoom, Streamlit permet de capturer les clics de l'utilisateur sur un graphique pour déclencher des actions — filtrer un tableau, mettre à jour un second graphique, ou stocker une sélection.

Interactivité par défaut

Chaque graphique Plotly affiché avec st.plotly_chart() offre ces interactions sans configuration :

InteractionGesteEffet
HoverSurvoler un élémentAffiche les valeurs (tooltip)
ZoomSélectionner une zone (clic + glisser)Zoom sur la zone sélectionnée
PanShift + clic + glisserDéplace la vue sans zoomer
ResetDouble-clicRevient à la vue initiale
Toggle sérieClic sur un élément de légendeMasque ou affiche la série correspondante

Tout cela fonctionne sans configuration. La barre d'outils en haut à droite offre aussi le téléchargement en PNG, la sélection rectangulaire ou lasso, et le zoom/dézoom.

Capturer les clics utilisateur avec on_select

Depuis Streamlit 1.29, on peut capturer les sélections sur un graphique Plotly :

python
event = st.plotly_chart(fig, use_container_width=True, on_select="rerun")

Le paramètre on_select="rerun" transforme le graphique en widget interactif : quand l'utilisateur clique ou sélectionne un élément, Streamlit déclenche un re-run complet du script et rend les informations de sélection accessibles via l'objet event.

Structure de l'objet event

L'objet retourné par st.plotly_chart() contient les informations sur les points sélectionnés :

python
event = st.plotly_chart(fig, use_container_width=True, on_select="rerun")

if event and event.selection.points:
    # Liste des points sélectionnés
    points = event.selection.points

    # Premier point sélectionné
    premier_point = points[0]
    valeur_x = premier_point["x"]       # Valeur sur l'axe X
    valeur_y = premier_point["y"]       # Valeur sur l'axe Y
    index_courbe = premier_point["curve_number"]  # Index de la trace

Structure des points

Chaque point dans event.selection.points est un dictionnaire contenant au minimum "x" et "y". Selon le type de graphique, d'autres clés sont disponibles : "label" pour un pie chart, "marker.size" pour un scatter avec size, etc. Utilisez st.write(event) pendant le développement pour explorer la structure complète.

Exemple complet : bar chart → filtre de tableau

Un bar chart par région. Quand l'utilisateur clique sur une barre, le tableau en dessous se filtre sur cette région.

Étape 1 — Créer le bar chart avec on_select

python
import plotly.express as px
import streamlit as st
import pandas as pd

# Données agrégées par région
df_regions = df.groupby("region")["chiffre_affaires"].sum().reset_index()

fig = px.bar(
    df_regions,
    x="region",
    y="chiffre_affaires",
    title="Chiffre d'affaires par région",
    labels={"chiffre_affaires": "CA (€)", "region": "Région"}
)
fig.update_layout(
    plot_bgcolor="rgba(0,0,0,0)",
    paper_bgcolor="rgba(0,0,0,0)"
)

# Capturer la sélection
event = st.plotly_chart(fig, use_container_width=True, on_select="rerun")

Étape 2 — Extraire la région sélectionnée

python
selected_region = None

if event and event.selection.points:
    selected_region = event.selection.points[0]["x"]
    st.info(f"Région sélectionnée : **{selected_region}**")

Étape 3 — Filtrer et afficher le tableau

python
if selected_region:
    df_filtered = df[df["region"] == selected_region]
    st.dataframe(df_filtered, use_container_width=True)
else:
    st.caption("Cliquez sur une barre pour filtrer le tableau.")
    st.dataframe(df, use_container_width=True)

Pattern complet

Ce pattern en trois étapes (graphique avec on_select → extraction de la valeur → filtrage des données) est réutilisable pour tout type de graphique. Il fonctionne avec les bar charts, les scatter plots, les pie charts, et les line charts.

Cross-filtering : mettre à jour un second graphique

Le même mécanisme met à jour un second graphique en fonction de la sélection :

python
# Bar chart principal — CA par région
event = st.plotly_chart(fig_regions, use_container_width=True, on_select="rerun")

# Si une région est sélectionnée, afficher l'évolution mensuelle de cette région
if event and event.selection.points:
    region = event.selection.points[0]["x"]
    df_evolution = df[df["region"] == region].groupby("mois")["chiffre_affaires"].sum().reset_index()

    fig_evolution = px.line(
        df_evolution,
        x="mois",
        y="chiffre_affaires",
        title=f"Évolution mensuelle — {region}",
        markers=True
    )
    st.plotly_chart(fig_evolution, use_container_width=True)

Ce pattern de cross-filtering est central dans les dashboards interactifs : cliquer sur un élément met à jour les autres visualisations.

Piège : le re-run réinitialise l'état

Re-run et perte d'état

Chaque on_select="rerun" déclenche un re-run complet du script Streamlit. Cela signifie que toutes les variables locales sont recalculées. Si vous avez besoin de conserver une sélection entre les re-runs (par exemple, permettre à l'utilisateur de cliquer sur une barre puis d'interagir avec un widget sans perdre sa sélection), utilisez st.session_state.

Conserver la sélection avec session_state

python
# Initialiser la clé dans session_state
if "selected_region" not in st.session_state:
    st.session_state.selected_region = None

# Capturer la sélection
event = st.plotly_chart(fig, use_container_width=True, on_select="rerun")

# Mettre à jour session_state si une nouvelle sélection est faite
if event and event.selection.points:
    st.session_state.selected_region = event.selection.points[0]["x"]

# Utiliser la valeur conservée
if st.session_state.selected_region:
    st.write(f"Région active : {st.session_state.selected_region}")
    df_filtered = df[df["region"] == st.session_state.selected_region]
    st.dataframe(df_filtered, use_container_width=True)

Ce pattern garantit que la sélection persiste même si d'autres widgets déclenchent un re-run.

Que fait le paramètre on_select='rerun' de st.plotly_chart() ?

Comment conserver la sélection d'un graphique Plotly entre les re-runs Streamlit ?

À retenir

Points clés

  • Les graphiques Plotly sont interactifs par défaut : hover, zoom, pan, toggle de séries
  • on_select="rerun" permet de capturer les clics et sélections de l'utilisateur
  • L'objet event.selection.points contient les données des points sélectionnés ("x", "y", etc.)
  • Pattern standard : graphique avec on_select → extraction de la valeur → filtrage des données
  • Le cross-filtering (cliquer sur un graphique met à jour les autres) est le pattern clé des dashboards interactifs
  • Utilisez st.session_state pour conserver une sélection entre les re-runs