Boostez le développement de vos applis data !
Corentin DUCLOUX
20/03/2024
Un framework python récent, lancé en 2019.
Et avant Streamlit, quâest ce quâil y avait ?
Flask \(\Rightarrow\) Prise en main trÚs complexe, plus adaptée pour les Software Engineers.
Plotly Dash \(\Rightarrow\) Prise en main plus simple que Flask, concept assez similaire à Shiny avec séparation des composants UI et server.
Objectif : Simplifier au maximum le dĂ©veloppement dâapplications Data.
User Interface ?
Inputs ?
Outputs ?
Interactions ?
Callbacks ?
Et pourquoi pas juste un script ?
\(\Rightarrow\) Lançons la démo pour voir de quoi Streamlit est capable.
app.py
import streamlit as st
st.set_page_config(page_icon="đ", page_title="PyApp")
st.title("đ Ma premiĂšre app super stylĂ©e")
st.markdown("Du *markdown* dans l'app ? **Rien de plus simple !**")
st.markdown("- Lien vers [`streamlit`](https://streamlit.io/)")
st.markdown(
"""
> Des couleurs ? :orange[orange], :red[rouge], :green[vert]
"""
)
st.code(
"""
[[i for i in range(5)] for j in range(2)]
# Du code non-exécutable
""",
language="python"
)
st.divider()đ et pour lancer lâappli :
st.set_page_config() pour configurer le favicon et le titre de lâonglet dans le navigateur
st.title() pour donner un titre Ă notre app
st.markdown() pour ajouter du texte avec différents types de formattage : italique, gras, ajout de liens, etc.
st.code() pour inclure du code non-exécutable provenant de différents langages : python, SQL, CSS, etc.
st.divider() pour tracer une ligne horizontale
IdentitĂ© DâEuler
\[ e^{i \pi} + 1 = 0 \]
Ajoutons ces quelques lignes de code.
Testons quelques widgets !
st.selectbox()st.button()st.columns() \(\Rightarrow\) Colonnesst.container() \(\Rightarrow\) Conteneurst.expander() \(\Rightarrow\) Expandeurst.tabs() \(\Rightarrow\) Tabsst.sidebar() \(\Rightarrow\) Sidebarst.popover() \(\Rightarrow\) Popovercolonne_1, colonne_2 = st.columns(2)
Explication visuelle par Donald J. Trump
On va changer notre interface utilisateur pour ajouter une Sidebar et regrouper nos widgets.
with st.sidebar:
prenom = st.text_input("đ€ Ecris ton prĂ©nom *cow-boy* !")
reussite = st.checkbox("Tu penses avoir ton année ?")
note_pf = st.number_input(
"Ta note en Concurrence et Innovation",
min_value=0,
max_value=5,
step=1
)
epanouissement = st.select_slider(
"Ton épanouissement en master",
range(11)
)On va ajouter quelques onglets (Tabs) Ă notre application pour diversifier lâinterface.
st.info()st.error()st.warning()st.success()with st.sidebar:
with st.expander("On regarde quelques messages ?"):
st.info(
f"Ton épanouissement en master : {epanouissement}/10",
icon="đšâđ«"
)
st.error(
f"Ta note en Concurrence et Innovation : {note_pf}",
icon="đ"
)
st.warning("Ceci est un avertissement gĂ©nĂ©rique", icon="â ")
st.success("Message de rĂ©ussite.", icon="â
")On a vu tout un tas dâĂ©lĂ©ments dâ
UI, mais on a pas vraiment interragi avec des données dignes de ce nom.
\(\Rightarrow\) Morale de lâhistoire : Installe polars
Exemple avec des données de cas de COVID-19 aux Etats-Unis entre 2020 et 2022 : + 2.5 millions de lignes !
import polars as pl
df_covid = pl.read_csv(
"https://raw.githubusercontent.com/nytimes/covid-19-data/master/us-counties.csv"
)ProblĂšmes
Deux décorateurs trÚs utiles :
@st.cache_data et @st.cache_resource
@st.cache_data
def import_covid_usa(link: str) -> pl.DataFrame:
"""Fonction d'import des données optimisée."""
return pl.read_csv(link)đĄ Et maintenant, observons la diffĂ©rence !
df_covid = import_covid_usa(
"https://raw.githubusercontent.com/nytimes/covid-19-data/master/us-counties.csv"
)Note
On attend une seule fois pour lâimport des donnĂ©es, ce qui est beaucoup plus satisfaisant pour lâutilisateur.
On a maintenant envie dâafficher nos donnĂ©es sous forme de tableau.
with tab_2:
st.dataframe(
df_covid,
hide_index=True,
use_container_width=True,
column_config={
"date": st.column_config.DateColumn("đ
Date", format="DD/MM/YYYY")
},
)\(\Rightarrow\) Grande flexibilitĂ© dans lâaffichage.
On va chercher à visualiser le nombre de morts par état à une certaine date.
with tab_3:
st.subheader("Nombre de personnes mortes de COVID-19 *(Noël 2020)*")
deaths_by_state_christmas = (
df_covid.filter(pl.col("date") == "2020-12-25")
.group_by("state")
.agg(pl.col("deaths").sum())
)
st.bar_chart(deaths_by_state_christmas, x="state", y="deaths")De nombreuses options de visualisation à la volée :
st.line_chart()st.scatter_chart()st.map()Mais comment tout ça marche ?
Au coeur de tous ces composants permettant de crĂ©er lâinterface utilisateur, il y a une classe : le DeltaGenerator.
Secrets management
def check_password():
"""Returns `True` if the user had the correct password."""
def password_entered():
"""Checks whether a password entered by the user is correct."""
if hmac.compare_digest(st.session_state["password"], st.secrets["password"]):
st.session_state["password_correct"] = True
del st.session_state["password"] # Don't store the password.
else:
st.session_state["password_correct"] = False
# Return True if the password is validated.
if st.session_state.get("password_correct", False):
return True
# Show input for password.
st.text_input(
"Mot de passe",
type="password",
on_change=password_entered,
key="password",
placeholder="Veuillez insérer le mot de passe pour accéder à l'application.",
)
if "password_correct" in st.session_state:
st.error("đ Mot de passe incorrect")
return False
if not check_password():
st.stop()API Reference : https://docs.streamlit.io/library/api-reference
