Introducció
Streamlit supports several different charting libraries, and our goal is to continually add support for more. Right now, the most basic library is Python - Matplotlib.
Then there are also interactive charting libraries like Vega Lite (2D charts) and deck.gl (maps and 3D charts).
And finally there a few chart types that are “native” to Streamlit, like st.line_chart
and st.area_chart
.
Projecte
Crea un projecte amb el nom streamlit-chart
:
uv init streamlit-chart
Activitat: Uber pickups
Faràs servir les funcionalitats bàsiques de Streamlit per crear una app interactiva explorant un conjunt de dades públic d’Uber de recollides i deixades a la ciutat de Nova York.
Quan acabis, sabràs com obtenir i posar en memòria cau dades, dibuixar gràfics, representar informació en un mapa i utilitzar ginys interactius, com un control lliscant, per filtrar resultats.
Afegeix una dependència amb Polars:
uv add polars
Obté dades
Ara que tens una app, el següent que necessites és obtenir el conjunt de dades d’Uber de recollides i deixades a Nova York.
Comencem escrivint una funció per carregar les dades. Afegeix aquest codi a l’script:
import polars as pl
DATA_URL = ('https://s3-us-west-2.amazonaws.com/'
'streamlit-demo-data/uber-raw-data-sep14.csv.gz')
def load_data(n_rows):
return pl.read_csv(DATA_URL, n_rows=n_rows, try_parse_dates=True)
Pots veure que load_data
és una funció normal que descarrega dades i les posa en un dataframe de Polars.
La funció accepta un únic paràmetre (n_rows
), que especifica el nombre de files que vols carregar al dataframe.
Ara prova la funció i revisa la sortida. A sota de la funció, afegeix aquestes línies:
# Create a text element and let the reader know the data is loading.
data_load_state = st.text('Loading data...')
# Load 10,000 rows of data into the dataframe.
data = load_data(10000)
# Notify the reader that the data was successfully loaded.
data_load_state.text('Loading data...done!')
Veureu alguns botons a la cantonada superior dreta de la teva app preguntant si vols tornar a executar-la. Tria Always rerun, i veuràs els canvis automàticament cada vegada que desis.
D’acord, això no impressiona gaire…
Resulta que descarregar dades i carregar 10.000 files en un dataframe triga força. Convertir la columna de data a datetime tampoc és ràpid. No vols tornar a carregar les dades cada vegada que s’actualitza l’app – per sort Streamlit permet posar-les en memòria cau.
Memòria cau sense esforç
Prova d’afegir @st.cache_data
abans de la declaració de load_data
:
@st.cache_data
def load_data(n_rows):
Després desa l’script i Streamlit tornarà a executar la teva app automàticament. Com que és la primera vegada que executes l’script amb @st.cache_data
, no veuràs cap canvi.
Modifiquem el fitxer una mica més per veure el poder de la memòria cau.
Substitueix la línia data_load_state.text('Loading data...done!')
per aquesta:
data_load_state.text("Done! (using st.cache_data)")
Ara desa. Veus com la línia que has afegit ha aparegut immediatament? Si ho penses, això és força sorprenent. Passa alguna cosa “màgica” en segon pla, i només cal una línia de codi per activar-ho.
Com funciona?
Prenem uns minuts per comentar com funciona realment @st.cache_data
.
Quan marques una funció amb l’anotació de memòria cau de Streamlit, li dius a Streamlit que sempre que es cridi la funció comprovi dues coses:
- Els paràmetres d’entrada que has fet servir en la crida.
- El codi dins de la funció.
Si és la primera vegada que Streamlit veu aquests dos elements, amb aquests valors exactes i en aquesta combinació exacta, executa la funció i n’emmagatzema el resultat a una memòria cau local. La propera vegada que es cridi la funció, si aquests dos valors no han canviat, Streamlit sap que pot saltar-se l’execució de la funció. En lloc d’això, llegeix la sortida des de la memòria cau local i la retorna — com per art de màgia.
“Però, un moment,” pots pensar, “això sona massa bé. Quines són les limitacions?”
N’hi ha algunes:
-
Streamlit només comprovarà canvis dins del directori de treball actual. Si actualitzes una llibreria de Python, la memòria cau de Streamlit només se n’adonarà si aquesta llibreria està instal·lada dins del teu directori de treball.
-
Si la funció no és determinista (és a dir, la sortida depèn d’aleatorietat) o si obté dades d’una font externa que varia en el temps (per exemple, un servei de cotitzacions en temps real), el valor en memòria cau no en serà conscient.
-
Finalment, evita mutar la sortida d’una funció emmagatzemada amb
st.cache_data
, ja que els valors a la memòria cau es guarden per referència.
Tot i que cal tenir en compte aquestes limitacions, sovint no són un problema. Quan no ho són, aquesta memòria cau és realment transformadora.
Now that you know how caching with Streamlit works, let’s get back to the Uber pickup data.
Ara que saps com funciona la memòria cau amb Streamlit, tornem a les dades de recollides d’Uber.
Inspecciona les dades en brut
Sempre és bona idea donar un cop d’ull a les dades en brut amb què treballes abans de començar. Afegim una subcapçalera i una taula de les dades en brut a l’app:
st.subheader("Raw data")
st.write(data)
A la guia de Conceptes bàsics pots aprendre que st.write
renderitza gairebé qualsevol cosa que li passis. En aquest cas, passes un dataframe i es mostra com una taula interactiva.
st.write
intenta fer el més adient segons el tipus de dades d’entrada. Si no fa el que esperes, pots utilitzar una instrucció especialitzada com st.dataframe
. Per a la llista completa, mira la referència de l’API.
Dibuixa un histograma
Després de donar un cop d’ull al conjunt de dades i veure què hi ha, fem un pas més i dibuixem un histograma per veure quines són les hores amb més recollides d’Uber a Nova York.
Per començar, afegeix una subcapçalera just sota la secció de dades en brut:
st.subheader('Number of pickups by hour')
A continuació afegeix una columna d’hores a la taula de dades:
df = df.with_columns(pl.col("Date/Time").dt.hour().alias("hour"))
A continuació dibuixa un histograma amb Altair:
import altair as alt
st.altair_chart(alt.Chart(df).mark_bar().encode(
x="hour",
y="count()"
))
Desa l’script.
Aquest histograma hauria d’aparèixer a l’app de seguida. Després d’una revisió ràpida, sembla que l’hora més concorreguda és les 17:00 (5 de la tarda).
Representa dades en un mapa
Amb l’histograma hem determinat quines són les hores més concorregudes per a recollides d’Uber, però i si volem saber on es concentren les recollides per la ciutat? Podries usar un diagrama de barres, però no seria fàcil d’interpretar si no coneixes molt bé les coordenades. Per mostrar la concentració de recollides, utilitzem la funció st.map()
de Streamlit per superposar les dades a un mapa de Nova York.
Afegeix una subcapçalera per a la secció:
st.subheader('Map of all pickups')
Utilitza la funció st.map()
per representar les dades:
df = df.rename({"Lat": "latitude", "Lon": "longitude"})
st.map(df)
Desa l’script.
El mapa és totalment interactiu. Prova de moure’l o fer zoom.
Després de dibuixar l’histograma, has determinat que l’hora amb més recollides d’Uber era les 17:00. Tornem a dibuixar el mapa per mostrar la concentració de recollides a les 17:00.
Localitza aquest fragment de codi:
st.subheader('Map of all pickups')
st.map(data)
Substitueix-lo per:
hour_to_filter = 17
df = df.filter(pl.col("Date/Time").dt.hour() == hour_to_filter)
st.subheader(f'Map of all pickups at {hour_to_filter}:00')
st.map(df)
Hauries de veure les dades actualitzar-se a l’instant.
Per dibuixar aquest mapa hem utilitzat la funció st.map
integrada a Streamlit, però si vols visualitzar dades cartogràfiques més complexes, dona un cop d’ull a st.pydeck_chart.
Filtra dades amb un control lliscant
A l’última secció, quan vas dibuixar el mapa, l’hora per filtrar resultats estava codificada al codi, però i si volem deixar que el lector filtri dinàmicament en temps real? Amb els ginys de Streamlit pots fer-ho.
Afegim un control lliscant a l’app amb el mètode st.slider()
.
Localitza hour_to_filter
i substitueix-lo per aquest codi:
hour_to_filter = st.slider("hour", 0, 23, 17) # min: 0h, max: 23h, default: 17h
Fes servir el slider i observa com s’actualitza el mapa en temps real.
Usa un botó per alternar dades
Els controls lliscants són només una manera de canviar dinàmicament la composició de la teva app. Fem servir la funció st.checkbox
per afegir una casella de selecció a l’app. La farem servir per mostrar/amagar la taula de dades en brut a la part superior de l’app.
Localitza aquestes línies:
st.subheader('Raw data')
st.write(data)
Substitueix-les per aquest codi:
if st.checkbox('Show raw data'):
st.subheader('Raw data')
st.write(data)
Segur que tens les teves pròpies idees. Quan acabis aquest tutorial, consulta tots els ginys que Streamlit ofereix a la Referència de l’API.