Streamlit 101: An in-depth introduction | by Shail Deliwala | Towards Data Science

Streamlit is an awesome new tool that allows engineers to quickly build highly interactive web applications around their data, machine learning models, and pretty much anything.
The best thing about Streamlit is it doesn’t require any knowledge of web development. If you know Python, you’re good to go!
Here’s the full code for this tutorial if you would like to follow along as you progress through the tutorial.
In one sentence: it gives you a blazingly fast, iterative, and interactive development loop.
Split your screen so your code editing tool is in one half and your browser is in the other, edit your code, and see your app updated instantly! My favorite part about Streamlit is how — in a matter of hours—it lets you go from Jupyter Notebook to a sleek web app worthy of presenting to a client.
Installation steps:
$ pip install streamlit$ streamlit hello
Imports:
import pandas as pdimport streamlit as stimport plotly.express as px
To run your Streamlit app:
$ streamlit run app.py
Airbnb does not officially release any of its data. Another group called Inside Airbnb periodically releases Airbnb listings and review data.
@st.cachedef get_data():    url = "http://data.insideairbnb.com/united-states/ny/new-york-city/2019-09-12/visualisations/listings.csv"    return pd.read_csv(url)df = get_data()
The st.cache decorator indicates that Streamlit will perform internal magic so that the data will be downloaded only once and cached for future use.
Behind the scenes, Streamlit keeps track of the function name, the code in the function body, and the input arguments we pass in the function call. Upon first invocation, it stores the function’s return value in a local cache. Upon subsequent invocations of the function with the exact same arguments, Streamlit returns the result from the local cache.
The main limitation of Streamlit’s data caching is that it cannot keep track of changes to the data happening outside the function body.
st.title("Streamlit 101: An in-depth introduction")st.markdown("Welcome to this in-depth introduction to [...].")st.header("Customary quote")st.markdown("> I just love to go home, no matter where I am [...]")
The above code renders the following.
st.title is suitable for the main title. For section titles, use st.header or st.subheader.
st.markdown renders any string written using Github-flavored Markdown. It also supports HTML but Streamlit advises against allowing it due to potential user security concerns.
This is the first thing we usually do when starting an exploratory analysis. st.dataframe renders pandas dataframes.
st.dataframe(df.head())
I love how it allows sorting the dataframe upon clicking any column header (notice the little chevron in the host_name header).
There’s a handy little button at the top right to switch to full-screen view. Great for viewing larger data frames without having to scroll too much.
It also supports styled dataframes.
st.code renders single-line as well as multi-line code blocks. There is also an option to specify the programming language.
st.code("""@st.cachedef get_data():    url = "http://data.insideairbnb.com/[...]"    return pd.read_csv(url)""", language="python")
Alternatively, using a with st.echo block executes the code within it and also renders it as a code section in the app.
Where are the most expensive Airbnb properties located?
st.map displays locations on a map without having to write a single line of boilerplate code to prepare a map object. The only requirement is that the dataframe must contain columns named lat/latitude or lon/longitude.
Unsurprisingly, Manhattan island has the highest concentration of expensive Airbnbs. Some are scattered over Brooklyn. The heftiest price tag is $10000.
st.deck_gl_chart allows more parameters to create more interesting and customized maps.
Streamlit has a multiselect widget that allows selecting or removing from a list of items. This lets us build a column selector widget for a dataframe.
cols = ["name", "host_name", "neighbourhood", "room_type", "price"]st_ms = st.multiselect("Columns", df.columns.tolist(), default=cols)
The multiselect widget is one of the most powerful and handy tools in Streamlit. One use aside from column selection is to filter a dataframe based on one or more values of a column. Another is to pick subplots for, say, a side-by-side comparison of ROC curves based on predictions of different models.
Which room types are most expensive on average?
st.table displays a static table. However, you cannot sort it by clicking a column header.
st.table(df.groupby("room_type").price.mean().reset_index()\.round(2).sort_values("price", ascending=False)\.assign(avg_price=lambda x: x.pop("price").apply(lambda y: "%.2f" % y)))
Sonder (NYC) is at the top with 387 property listings. Blueground is second with 240 listings. Following are randomly chosen listings from the two rendered as JSON using st.json.
Streamlit renders fully interactive JSON sections with support to collapse/expand objects and arrays, and copy-to-clipboard functionality.
We display a histogram of property prices displayed as a Plotly chart using st.plotly_chart.
We use st.slider to provide a slider that allows selecting a custom range for the histogram. We tuck it away into a sidebar.
values = st.sidebar.slider(“Price range”, float(df.price.min()), 1000., (50., 300.))f = px.histogram(df.query(f”price.between{values}”), x=”price”, nbins=15, title=”Price distribution”)f.update_xaxes(title=”Price”)f.update_yaxes(title=”No. of listings”)st.plotly_chart(f)
The tallest bar corresponds to the $60–79 price range, which has 7229 listings.
Note: For this tutorial, I limited the maximum value of the slider to 1000 so the range selection would be clearly visible.
availability_365 indicates the number of days a property is available throughout the year. We examine summary statistics of availability_365 by neighborhood group.
Using st.radio, we show a list of neighborhood groups to select from. By default, we exclude listings with price ≥ $200 and provide an Include expensive listings checkbox using st.checkbox.
st.write is, sort of, an umbrella function that accepts strings, dataframes, dictionaries, plots, maps, and so on (full list in the documentation). It allows passing in multiple arguments, and its behavior depends on their types.
st.write("Using a radio button restricts selection to only one option at a time.")neighborhood = st.radio("Neighborhood", df.neighbourhood_group.unique())show_exp = st.checkbox("Include expensive listings")
At 169 days, Brooklyn has the lowest average availability. At 226, Staten Island has the highest average availability. If we include expensive listings (price>=$200), the numbers are 171 and 230 respectively.
Note: There are 18431 records with availability_365 0 (zero), which I've ignored.
st.pyplot renders plots built using matplotlib like the one below.
df.query("availability_365>0")\.groupby("neighbourhood_group")\.availability_365.mean()\.plot.bar(rot=0)\.set(title="Average availability by neighborhood group",xlabel="Neighborhood group", ylabel="Avg. availability (in no. of days)")st.pyplot()
We want to view properties with number of reviews falling within a range that we can customize.
In the sidebar, we provide a numeric range selector using st.number_input. If minimum > maximum, we display an error message using st.error.
minimum = st.sidebar.number_input("Minimum", min_value=0)maximum = st.sidebar.number_input("Maximum", min_value=0, value=5)if minimum > maximum:    st.error("Please enter a valid range")else:    df.query("@minimum<=number_of_reviews<=@maximum")
486 is the highest number of reviews. Two listings have that many reviews. Both are in the East Elmhurst neighborhood and are private rooms with prices $65 and $45. In general, listings with >400 reviews are priced below $100. A few are between $100 and $200, and only one is priced above $200.
Use st.image to show images of cats, puppies, feature importance plots, tagged video frames, and so on.
Now for a bit of fun.
pics = {    "Cat": "https://cdn.pixabay.com/photo/2016/09/24/22/20/cat-1692702_960_720.jpg",    "Puppy": "https://cdn.pixabay.com/photo/2019/03/15/19/19/puppy-4057786_960_720.jpg",    "Sci-fi city": "https://storage.needpix.com/rsynced_images/science-fiction-2971848_1280.jpg"}pic = st.selectbox("Picture choices", list(pics.keys()), 0)st.image(pics[pic], use_column_width=True, caption=pics[pic])
Notice how in the Number of Reviews section above, we wrote df.query("@minimum<=number_of_reviews<=@maximum")on its own line without wrapping it in a call to st.dataframe. This still rendered a dataframe because Streamlit detects a variable or literal on its own line and uses st.write to render it.
We’ve covered interactive widgets, dataframes, tables, images, Markdown, plot rendering, maps, and textual content. Streamlit allows modification of existing elements and showing progress, which we have not covered in this tutorial. For instance, you can add rows to an existing table or add new data to a chart. You can also show a progress bar for long-running processes.
Congratulations, you’re all set to start building your own Streamlit apps.
When you run the app created for this tutorial, do click the Celebrate! button rendered by the code below.
st.markdown("## Party time!")st.write("Yay! You're done with this tutorial of Streamlit. Click below to celebrate.")btn = st.button("Celebrate!")if btn:    st.balloons()
My next article will be about my silver medal winning (rank 35 / top 4%) solution to Walmart Shopping Trip Type Classification competition on Kaggle.
Full code of the Streamlit app created for this tutorial: https://github.com/shaildeliwala/experiments/blob/master/streamlit.py
From Adrien Treuille, the co-founder of Streamlit: https://towardsdatascience.com/coding-ml-tools-like-you-code-ml-models-ddba3357eace
Streamlit API documentation: https://streamlit.io/docs/api.html
Streamlit tutorial: https://streamlit.io/docs/tutorial2/
Streamlit demo video: https://youtu.be/B2iAodr0fOo
Airbnb NYC listings data (unofficial): http://data.insideairbnb.com/united-states/ny/new-york-city/2019-09-12/visualisations/listings.csv
Plotly histogram documentation: https://plot.ly/python/histograms/