Avancé

Mapper une réponse API sur un graphique

Scénario courant : interroger une API (ou un repository), récupérer des données sous forme de liste de dictionnaires, et les afficher dans un graphique. Cette page couvre le flux du endpoint au graphique dans Streamlit.

Du endpoint au graphique : le flux complet

Chargement du diagramme…

Cinq étapes linéaires :

  1. Appel — requête HTTP ou appel direct au repository
  2. Données — réponse JSON (liste de dictionnaires)
  3. Conversionpd.DataFrame() pour obtenir un DataFrame
  4. Graphique — Plotly Express consomme directement le DataFrame
  5. Affichagest.plotly_chart() intègre le graphique dans Streamlit

Conversion liste de dicts vers DataFrame

Depuis un repository (accès direct)

python
import pandas as pd

data = repo.get_par_region(annee=2024)
# data = [{"region": "IDF", "chiffre_affaires": 1250000}, ...]

df = pd.DataFrame(data)

Depuis une API REST (via requests)

python
import requests

response = requests.get("http://localhost:5000/api/v1/ventes/par-region?annee=2024")
df = pd.DataFrame(response.json()["data"])

Repository vs API

Dans ce cours, vous utilisez principalement le repository en accès direct (sans passer par HTTP). Le résultat est le même : une liste de dictionnaires convertie en DataFrame. L'approche API est montrée pour illustrer le pattern complet, mais dans votre dashboard Streamlit vous appelez directement les méthodes du repository.

Quelle fonction pandas permet de convertir une liste de dictionnaires en DataFrame ?

Cas concret : dashboard avec 3 graphiques

Un exemple intégrant trois graphiques dans un dashboard Streamlit. Ce pattern est celui des exercices.

Chargement centralisé des données

python
@st.cache_data(ttl=300)
def load_data(region, annee):
    return {
        "par_region": pd.DataFrame(repo.get_par_region(annee=annee)),
        "evolution": pd.DataFrame(repo.get_evolution_mensuelle(region=region, annee=annee)),
        "repartition": pd.DataFrame(repo.get_par_categorie(region=region, annee=annee))
    }

data = load_data(region, annee)

Centraliser le chargement

Regrouper les appels de données dans une seule fonction cachée garantit la cohérence (mêmes filtres) et une invalidation de cache groupée quand les paramètres changent.

Disposition en colonnes avec graphiques

python
col1, col2 = st.columns([2, 1])

with col1:
    fig_bar = px.bar(
        data["par_region"],
        x="region",
        y="chiffre_affaires",
        title="CA par région"
    )
    st.plotly_chart(fig_bar, use_container_width=True)

with col2:
    fig_pie = px.pie(
        data["repartition"],
        names="categorie",
        values="chiffre_affaires",
        hole=0.4,
        title="Répartition par catégorie"
    )
    st.plotly_chart(fig_pie, use_container_width=True)

fig_line = px.line(
    data["evolution"],
    x="mois",
    y="chiffre_affaires",
    title="Évolution mensuelle",
    markers=True
)
st.plotly_chart(fig_line, use_container_width=True)

Organisation de la page

st.columns([2, 1]) crée deux colonnes de largeurs inégales :

  • Gauche (ratio 2) : le bar chart, plus large car il affiche plusieurs barres
  • Droite (ratio 1) : le donut, compact par nature
  • Le line chart occupe toute la largeur en dessous

use_container_width=True

Ajoutez toujours use_container_width=True à st.plotly_chart(). Sans ce paramètre, le graphique utilise une largeur fixe par défaut qui ne s'adapte pas à la colonne. Le résultat est souvent un graphique trop étroit ou qui déborde.

Pourquoi est-il recommandé de regrouper les appels de données dans une seule fonction cachée ?

À retenir

Points clés

  • Le flux standard est : API/Repository → liste de dicts → pd.DataFrame() → px.graphique() → st.plotly_chart()
  • pd.DataFrame(data) convertit directement une liste de dictionnaires
  • Centralisez le chargement dans une fonction unique décorée @st.cache_data
  • Utilisez st.columns() pour disposer plusieurs graphiques côte à côte
  • Toujours passer use_container_width=True à st.plotly_chart()