9 · Charts, uploads & a polished dashboard
Round out the dashboard: `st.line_chart`/`st.bar_chart`/`st.pyplot` to visualize, `st.file_uploader` to batch-score an uploaded CSV, and `st.download_button` to hand the results back. The full flow — upload a CSV → score every row → download the scored file — is the everyday Streamlit batch-prediction pattern.
Charts (`st.line_chart`/`st.bar_chart`/`st.pyplot`) turn predictions into a readable dashboard, and the batch-scoring loop is the workhorse: `st.file_uploader` accepts a CSV → read it into a DataFrame → `model.predict` on ALL rows at once → show + offer the scored file via `st.download_button`. Upload → batch-score → download is the everyday human-in-the-loop pattern for scoring many records without writing an API.
Without this:
Without charts the dashboard is just numbers; and without the upload→score→download loop, a user who needs to score a whole spreadsheet of customers would have to call the API row by row instead of dropping in one CSV.
Lesson 7 scored one customer; lesson 8 made the app fast and laid-out. This lesson makes it a polished dashboard: visualize predictions with charts, and let a user batch-score a whole CSV by uploading it and downloading the scored result — no API, no code, just drag-drop-download.
Charts — one line each. Streamlit's built-in charts take a DataFrame or array and render an interactive plot:
st.line_chart(df)— trends over an index (a probability over time, a metric per day).st.bar_chart(df)— categorical comparisons (predictions per segment).st.pyplot(fig)— drop in any Matplotlib figure when you need full control (a histogram of churn scores, a confusion matrix). You build thefigas usual and hand it tost.pyplot.
A chart turns a column of raw probabilities into something a stakeholder can read at a glance — the whole point of a human-facing dashboard.
st.file_uploader — take a file from the user. uploaded = st.file_uploader("Upload customers CSV", type="csv") renders a drag-and-drop box and returns a file-like object once the user picks a file (or None before then). You pass it straight to pd.read_csv(uploaded) to get a DataFrame — the user's whole spreadsheet, in your hands.
Batch-score the whole DataFrame at once. This is the key efficiency: scikit-learn's model.predict is vectorized — give it a 2-D array of many rows and it returns many predictions in one call. So you don't loop row by row; you select the feature columns in trained order, pass the entire block, and get a prediction per row: df["prediction"] = model.predict(df[FEATURES]). One call scores the whole file.
st.download_button — hand the results back. Once you've added a prediction column, the user wants the file back. st.download_button("Download scored CSV", df.to_csv(index=False), "scored.csv") renders a button that downloads the bytes you give it — here the scored DataFrame as CSV. That closes the loop.
The full pattern: upload → batch-score → download. Put together: the user drops in a CSV, you read it, score every row with one vectorized predict, show a chart and a preview table, and offer a download button for the scored file. It's the everyday "score my spreadsheet" workflow — a non-coder gets bulk predictions with zero engineering, and you never had to build or call an API for it.
The read-along cell assembles the polished dashboard: an upload, a one-call batch score, a chart, a preview, and a download button.
A Streamlit batch-scoring dashboard: `st.file_uploader` reads a CSV, one vectorized `model.predict_proba` scores every row, `st.bar_chart`/`st.dataframe` visualize, and `st.download_button` returns the scored file.
In the Streamlit batch-scoring dashboard, what is the correct flow for scoring an uploaded spreadsheet of customers?
- Streamlit charts are one line each: `st.line_chart`/`st.bar_chart` take a DataFrame, and `st.pyplot(fig)` embeds any Matplotlib figure for full control.
- Batch-score with ONE vectorized `model.predict(df[FEATURES])` over the whole DataFrame — never a per-row loop, which is slower and pointless.
- The upload→batch-score→download loop (`st.file_uploader` → score → `st.download_button`) lets a non-coder score a whole spreadsheet with no API.
Batch scoring a CSV through a Streamlit upload is how analysts routinely get bulk predictions — drop in a file of records, download it with a prediction column, no engineering involved.
If you remove it: Without the upload-and-score loop, a user with a spreadsheet of customers has no way to get bulk predictions short of calling the API once per row by hand.