Spaces:
Running
Running
app files:
Browse files
app.py
CHANGED
@@ -3,19 +3,27 @@
|
|
3 |
|
4 |
# day 2/3 -- "grab bag" of other things
|
5 |
# multi-page apps? ==> maybe day 2? ==> does this work with HF apps??
|
6 |
-
|
7 |
-
# embedding streamlit spaces on other webpages? wait until Jekyll? https://huggingface.co/docs/hub/en/spaces-sdks-streamlit#embed-streamlit-spaces-on-other-webpages
|
8 |
-
# how to search/duplicate other spaces on HF (make sure you cite this!)
|
9 |
|
10 |
-
# start with "this is how we publish with streamlit" -- README file, requirements, etc
|
11 |
-
# ---> make sure to mention the "yaml-ness" of the README file
|
12 |
-
# ---> say that the easiest way to start is with an already hosted app on HF -- luckily we alread have a lab on this!
|
13 |
-
# ---> make this like the "jekyll updates" folders that have all these prep and in class files in them
|
14 |
-
# Then: more streamlit extras with all of those ones listed above
|
15 |
|
16 |
-
|
17 |
-
# 1.
|
18 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
19 |
|
20 |
|
21 |
# Let's start by copying things we did last time
|
@@ -67,12 +75,12 @@ with tab2:
|
|
67 |
|
68 |
|
69 |
################################################
|
70 |
-
#
|
71 |
################################################
|
72 |
|
73 |
st.header('Requirements, README file, Pushing to HuggingFace')
|
74 |
|
75 |
-
###
|
76 |
|
77 |
# Let's say we want to add in some matplotlib plots from some data we read
|
78 |
# in with Pandas.
|
@@ -94,21 +102,345 @@ df['Seg_income'].plot(kind='hist', ax=ax)
|
|
94 |
# We need to use the streamlit-specific way of showing matplotlib plots: https://docs.streamlit.io/develop/api-reference/charts/st.pyplot
|
95 |
st.pyplot(fig)
|
96 |
|
97 |
-
###
|
98 |
# In order to push these changes to HF and have things actually show up we need to
|
99 |
# add the packages we've added to our requirements.txt file.
|
100 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
101 |
# While we're doing this, let's also take a look at the README.md file!
|
102 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
103 |
|
104 |
################################################
|
105 |
-
#
|
106 |
################################################
|
107 |
|
108 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
109 |
|
110 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
111 |
|
112 |
################################################
|
113 |
-
#
|
114 |
################################################
|
|
|
3 |
|
4 |
# day 2/3 -- "grab bag" of other things
|
5 |
# multi-page apps? ==> maybe day 2? ==> does this work with HF apps??
|
6 |
+
# Week 12 -- https://docs.streamlit.io/develop/tutorials/databases <- touch on but say we'll be just doing csv files
|
7 |
+
# Week 12 -- embedding streamlit spaces on other webpages? wait until Jekyll? https://huggingface.co/docs/hub/en/spaces-sdks-streamlit#embed-streamlit-spaces-on-other-webpages
|
|
|
8 |
|
|
|
|
|
|
|
|
|
|
|
9 |
|
10 |
+
#######################################################
|
11 |
+
# 1. Getting setup -- using our HF template
|
12 |
+
#######################################################
|
13 |
+
|
14 |
+
# We have a few options for how to proceed. I'll start by showing the process in
|
15 |
+
# PL and then I'll move to my local installation of my template so that I can make
|
16 |
+
# sure I am pushing code at various intervals so folks can check that out.
|
17 |
+
|
18 |
+
# NOTE: during this process, you can click on "Always Rerun" for automatic updates.
|
19 |
+
|
20 |
+
# See the class notes on this with some photos for reference!
|
21 |
+
# **this has to be implemented!**
|
22 |
+
|
23 |
+
|
24 |
+
###################################################################
|
25 |
+
# 2. Review of where we got to last time, in template app.py file
|
26 |
+
###################################################################
|
27 |
|
28 |
|
29 |
# Let's start by copying things we did last time
|
|
|
75 |
|
76 |
|
77 |
################################################
|
78 |
+
# 3. Adding features, Pushing to HF
|
79 |
################################################
|
80 |
|
81 |
st.header('Requirements, README file, Pushing to HuggingFace')
|
82 |
|
83 |
+
### 3.1 Make a plot ###
|
84 |
|
85 |
# Let's say we want to add in some matplotlib plots from some data we read
|
86 |
# in with Pandas.
|
|
|
102 |
# We need to use the streamlit-specific way of showing matplotlib plots: https://docs.streamlit.io/develop/api-reference/charts/st.pyplot
|
103 |
st.pyplot(fig)
|
104 |
|
105 |
+
### 3.2 Push these changes to HF -- requirements.txt ###
|
106 |
# In order to push these changes to HF and have things actually show up we need to
|
107 |
# add the packages we've added to our requirements.txt file.
|
108 |
|
109 |
+
st.write('''The requirements.txt file contains all the packages needed
|
110 |
+
for our app to run. These include (for our application):''')
|
111 |
+
st.code('''
|
112 |
+
streamlit
|
113 |
+
altair
|
114 |
+
numpy
|
115 |
+
pandas
|
116 |
+
matplotlib
|
117 |
+
''')
|
118 |
+
|
119 |
+
# NOTE: for any package you want to use in your app.py file, you must include it in
|
120 |
+
# the requirements.txt file!
|
121 |
+
|
122 |
+
### 3.3 Push these changes to HF -- README.md ###
|
123 |
+
|
124 |
# While we're doing this, let's also take a look at the README.md file!
|
125 |
|
126 |
+
st.header('Build in HF: README.md & requirements.txt files')
|
127 |
+
|
128 |
+
st.code('''
|
129 |
+
---
|
130 |
+
title: Prep notebook -- My Streamlit App
|
131 |
+
emoji: 🏢
|
132 |
+
colorFrom: blue
|
133 |
+
colorTo: gray
|
134 |
+
sdk: streamlit
|
135 |
+
sdk_version: 1.36.0
|
136 |
+
app_file: app.py
|
137 |
+
pinned: false
|
138 |
+
license: mit
|
139 |
+
---
|
140 |
+
''')
|
141 |
+
|
142 |
+
# Some important things to note here:
|
143 |
+
|
144 |
+
st.write('Some important items to note about these:')
|
145 |
+
st.markdown('''
|
146 |
+
* the "emoji" is what will show up as an identifier on your homepage
|
147 |
+
* the sdk *must* be streamlit
|
148 |
+
* the "app_file" *must* link to the app file you are developing in
|
149 |
+
''')
|
150 |
|
151 |
################################################
|
152 |
+
# 4. TODO Quick intro to widgets
|
153 |
################################################
|
154 |
|
155 |
+
st.header('Widgets in Streamlit apps')
|
156 |
+
|
157 |
+
### 4.1 Widget basics: A few widget examples ###
|
158 |
+
|
159 |
+
st.markdown("""
|
160 |
+
These will be very similar to how we used the `ipywidgets` package in Jupyter notebooks.
|
161 |
+
""")
|
162 |
+
|
163 |
+
st.markdown("""
|
164 |
+
We won't go over all of them, but you can check out the [list of widgets](https://docs.streamlit.io/develop/api-reference/widgets)
|
165 |
+
linked.
|
166 |
+
""")
|
167 |
+
|
168 |
+
st.markdown("""Let's try a few!""")
|
169 |
+
|
170 |
+
st.subheader('Feedback Widget')
|
171 |
+
|
172 |
+
st.markdown("""
|
173 |
+
For example, we could try the [feedback widget](https://docs.streamlit.io/develop/api-reference/widgets/st.feedback).
|
174 |
+
"""
|
175 |
+
)
|
176 |
+
st.markdown("""
|
177 |
+
If we check out the docs for this widget, we see some familiar looking functions like
|
178 |
+
`on_change` and the example they give looks very similar to an
|
179 |
+
"observation" function that we built before using widgets:
|
180 |
+
""")
|
181 |
+
|
182 |
+
st.code(
|
183 |
+
"""
|
184 |
+
sentiment_mapping = ["one", "two", "three", "four", "five"]
|
185 |
+
selected = st.feedback("stars")
|
186 |
+
if selected is not None:
|
187 |
+
st.markdown(f"You selected {sentiment_mapping[selected]} star(s).")
|
188 |
+
""")
|
189 |
+
|
190 |
+
# Let's give this a shot!
|
191 |
+
|
192 |
+
st.write("How great are you feeling right now?")
|
193 |
+
sentiment_mapping = ["one", "two", "three", "four", "five"] # map to these numers
|
194 |
+
selected = st.feedback("stars")
|
195 |
+
if selected is not None: # make sure we have a selection
|
196 |
+
st.markdown(f"You selected {sentiment_mapping[selected]} star(s).")
|
197 |
+
if selected < 1:
|
198 |
+
st.markdown('Sorry to hear you are so sad :(')
|
199 |
+
elif selected < 3:
|
200 |
+
st.markdown('A solid medium is great!')
|
201 |
+
else:
|
202 |
+
st.markdown('Fantastic you are having such a great day!')
|
203 |
+
|
204 |
+
st.subheader('Radio Buttons')
|
205 |
+
|
206 |
+
st.markdown("""
|
207 |
+
Let's try out a [radio button](https://docs.streamlit.io/develop/api-reference/widgets/st.radio) example.
|
208 |
+
""")
|
209 |
+
|
210 |
+
favoriteViz = st.radio(
|
211 |
+
"What's your visualization tool so far?",
|
212 |
+
[":rainbow[Streamlit]", "vega-lite :sparkles:", "matplotlib :material/Home:"],
|
213 |
+
captions=[
|
214 |
+
"New and cool!",
|
215 |
+
"So sparkly.",
|
216 |
+
"Familiar and comforting.",
|
217 |
+
],
|
218 |
+
)
|
219 |
+
|
220 |
+
if favoriteViz == ":rainbow[Streamlit]":
|
221 |
+
st.write("You selected Streamlit!")
|
222 |
+
else:
|
223 |
+
st.write("You didn't select Streamlit but that's ok, Data Viz still likes you :grin:")
|
224 |
+
|
225 |
+
st.markdown("""
|
226 |
+
Note here that we made use of text highlight [colors](https://docs.streamlit.io/develop/api-reference/text/st.markdown)
|
227 |
+
and [emoji's](https://streamlit-emoji-shortcodes-streamlit-app-gwckff.streamlit.app/)
|
228 |
+
and [icons](https://fonts.google.com/icons?icon.set=Material+Symbols&icon.style=Rounded).
|
229 |
+
""")
|
230 |
+
|
231 |
+
### 4.2 Connecting widgets with plots ###
|
232 |
+
|
233 |
+
st.subheader('Connecting Widgets and Plots')
|
234 |
+
|
235 |
+
st.markdown("""
|
236 |
+
We can also
|
237 |
+
""")
|
238 |
+
|
239 |
+
st.markdown("""
|
240 |
+
There are actually [many types of charts](https://docs.streamlit.io/develop/api-reference/charts)
|
241 |
+
supported in Streamlit (including the Streamlit-based "Simple Charts"),
|
242 |
+
though we will just mainly be focusing on [Altair-related](https://docs.streamlit.io/develop/api-reference/charts/st.altair_chart) plots
|
243 |
+
and their interactivity options since we'll also be making use of these when
|
244 |
+
we move to building Jekyll webpages.
|
245 |
+
""")
|
246 |
+
|
247 |
+
st.markdown("""Since `matplotlib` is relatively familiar though, let's do a quick
|
248 |
+
example using `pandas` and `matplotlib` to plot as
|
249 |
+
Streamlit [does support `matplotlib`](https://docs.streamlit.io/develop/api-reference/charts/st.pyplot)
|
250 |
+
as a plotting engine. """)
|
251 |
+
|
252 |
+
st.markdown("""First, let's just make a simple plot with `pandas` and `matplotlib`.
|
253 |
+
Let's re-do the matplotlib plots we did before with the mobility dataset
|
254 |
+
with some interactivity. """)
|
255 |
+
|
256 |
+
import pandas as pd
|
257 |
+
import numpy as np
|
258 |
+
|
259 |
+
# first, let's make a static plot:
|
260 |
+
st.write("We'll start with a static plot:")
|
261 |
+
# read in dataset
|
262 |
+
df = pd.read_csv("https://raw.githubusercontent.com/UIUC-iSchool-DataViz/is445_data/main/mobility.csv")
|
263 |
+
|
264 |
+
# make bins along student-teacher ratio
|
265 |
+
bins = np.linspace(df['Student_teacher_ratio'].min(),df['Student_teacher_ratio'].max(), 10)
|
266 |
+
|
267 |
+
# make pivot table
|
268 |
+
table = df.pivot_table(index='State', columns=pd.cut(df['Student_teacher_ratio'], bins), aggfunc='size')
|
269 |
+
|
270 |
+
# our plotting code before was:
|
271 |
+
st.code("""
|
272 |
+
import matplotlib.pyplot as plt
|
273 |
+
|
274 |
+
fig,ax = plt.subplots(figsize=(10,8))
|
275 |
+
ax.imshow(table.values, cmap='hot', interpolation='nearest')
|
276 |
+
ax.set_yticks(range(len(table.index)))
|
277 |
+
ax.set_yticklabels(table.index)
|
278 |
+
plt.show()
|
279 |
+
""")
|
280 |
+
|
281 |
+
st.write("Let's translate it into something that will work with Streamlit:")
|
282 |
+
|
283 |
+
import matplotlib.pyplot as plt
|
284 |
|
285 |
+
fig,ax = plt.subplots() # this changed
|
286 |
+
ax.imshow(table.values, cmap='hot', interpolation='nearest')
|
287 |
+
ax.set_yticks(range(len(table.index)))
|
288 |
+
ax.set_yticklabels(table.index)
|
289 |
+
|
290 |
+
st.pyplot(fig) # this is different
|
291 |
+
|
292 |
+
st.markdown("""But this is too big! The trick is that we can save this as a buffer: """)
|
293 |
+
|
294 |
+
from io import BytesIO
|
295 |
+
|
296 |
+
fig,ax = plt.subplots(figsize=(4,8)) # this changed
|
297 |
+
ax.imshow(table.values, cmap='hot', interpolation='nearest')
|
298 |
+
ax.set_yticks(range(len(table.index)))
|
299 |
+
ax.set_yticklabels(table.index)
|
300 |
+
|
301 |
+
buf = BytesIO()
|
302 |
+
fig.tight_layout()
|
303 |
+
fig.savefig(buf, format="png")
|
304 |
+
st.image(buf, width = 500) # can mess around with width, figsize/etc
|
305 |
+
|
306 |
+
st.write("Now, let's make this interactive")
|
307 |
+
st.markdown("""We'll first use the [multiselect](https://docs.streamlit.io/develop/api-reference/widgets/st.multiselect)
|
308 |
+
tool in order to allow for multiple state selection. """)
|
309 |
+
|
310 |
+
# vertical alignment so they end up side by side
|
311 |
+
fig_col, controls_col = st.columns([2,1], vertical_alignment='center')
|
312 |
+
|
313 |
+
# multi-select
|
314 |
+
states_selected = controls_col.multiselect('Which states do you want to view?', table.index.values)
|
315 |
+
|
316 |
+
if len(states_selected) > 0:
|
317 |
+
df_subset = df[df['State'].isin(states_selected)] # changed
|
318 |
+
|
319 |
+
# make pivot table -- changed
|
320 |
+
table_sub = df_subset.pivot_table(index='State',
|
321 |
+
columns=pd.cut(df_subset['Student_teacher_ratio'], bins),
|
322 |
+
aggfunc='size')
|
323 |
+
|
324 |
+
base_size = 4
|
325 |
+
# this resizing doesn't 100% work great
|
326 |
+
#factor = len(table.index)*1.0/df['State'].nunique()
|
327 |
+
#if factor == 0: factor = 1 # for non-selections
|
328 |
+
#fig,ax = plt.subplots(figsize=(base_size,2*base_size*factor)) # this changed too for different size
|
329 |
+
fig,ax = plt.subplots(figsize=(base_size,2*base_size)) # this changed too for different size
|
330 |
+
# extent is (xmin, xmax, ymax (buttom), ymin (top))
|
331 |
+
extent = [bins.min(), bins.max(), 0, len(table_sub.index)]
|
332 |
+
ax.imshow(table_sub.values, cmap='hot', interpolation='nearest',
|
333 |
+
extent=extent)
|
334 |
+
ax.set_yticks(range(len(table_sub.index)))
|
335 |
+
ax.set_yticklabels(table_sub.index)
|
336 |
+
#ax.set_xticklabels(bins)
|
337 |
+
|
338 |
+
buf = BytesIO()
|
339 |
+
fig.tight_layout()
|
340 |
+
fig.savefig(buf, format="png")
|
341 |
+
fig_col.image(buf, width = 400) # changed here to fit better
|
342 |
+
else:
|
343 |
+
fig,ax = plt.subplots(figsize=(4,8)) # this changed
|
344 |
+
extent = [bins.min(), bins.max(), 0, len(table.index)]
|
345 |
+
ax.imshow(table.values, cmap='hot', interpolation='nearest', extent=extent)
|
346 |
+
ax.set_yticks(range(len(table.index)))
|
347 |
+
ax.set_yticklabels(table.index)
|
348 |
+
#ax.set_xticklabels(bins)
|
349 |
+
|
350 |
+
buf = BytesIO()
|
351 |
+
fig.tight_layout()
|
352 |
+
fig.savefig(buf, format="png")
|
353 |
+
fig_col.image(buf, width = 500) # can mess around with width, figsize/etc
|
354 |
+
|
355 |
+
|
356 |
+
st.markdown("""
|
357 |
+
Now let's add more in by including a [range slider](https://docs.streamlit.io/develop/api-reference/widgets/st.slider)
|
358 |
+
widget.
|
359 |
+
""")
|
360 |
+
|
361 |
+
# vertical alignment so they end up side by side
|
362 |
+
fig_col2, controls_col2 = st.columns([2,1], vertical_alignment='center')
|
363 |
+
|
364 |
+
# multi-select
|
365 |
+
states_selected2 = controls_col2.multiselect('Which states do you want to view?',
|
366 |
+
table.index.values, key='unik1155')
|
367 |
+
# had to pass unique key to have double widgets with same value
|
368 |
+
|
369 |
+
# range slider -- added
|
370 |
+
student_teacher_ratio_range = controls_col2.slider("Range of student teacher ratio:",
|
371 |
+
df['Student_teacher_ratio'].min(),
|
372 |
+
df['Student_teacher_ratio'].max(),
|
373 |
+
(0.25*df['Student_teacher_ratio'].mean(),
|
374 |
+
0.75*df['Student_teacher_ratio'].mean()))
|
375 |
+
|
376 |
+
# note all the "2's" here, probably will just update the original one
|
377 |
+
if len(states_selected2) > 0: # here we set a default value for the slider, so no need to have a tag
|
378 |
+
min_range = student_teacher_ratio_range[0] # added
|
379 |
+
max_range = student_teacher_ratio_range[1] # added
|
380 |
+
|
381 |
+
df_subset2 = df[(df['State'].isin(states_selected2)) & (df['Student_teacher_ratio'] >= min_range) & (df['Student_teacher_ratio']<=max_range)] # changed
|
382 |
+
|
383 |
+
# just 10 bins over the full range --> changed
|
384 |
+
bins2 = 10 #np.linspace(df['Student_teacher_ratio'].min(),df['Student_teacher_ratio'].max(), 10)
|
385 |
+
|
386 |
+
# make pivot table -- changed
|
387 |
+
table_sub2 = df_subset2.pivot_table(index='State',
|
388 |
+
columns=pd.cut(df_subset2['Student_teacher_ratio'], bins2),
|
389 |
+
aggfunc='size')
|
390 |
+
|
391 |
+
base_size = 4
|
392 |
+
fig2,ax2 = plt.subplots(figsize=(base_size,2*base_size)) # this changed too for different size
|
393 |
+
extent2 = [df_subset2['Student_teacher_ratio'].min(),
|
394 |
+
df_subset2['Student_teacher_ratio'].max(),
|
395 |
+
0, len(table_sub2.index)]
|
396 |
+
ax2.imshow(table_sub2.values, cmap='hot', interpolation='nearest', extent=extent2)
|
397 |
+
ax2.set_yticks(range(len(table_sub2.index)))
|
398 |
+
ax2.set_yticklabels(table_sub2.index)
|
399 |
+
#ax2.set_xticklabels()
|
400 |
+
|
401 |
+
buf2 = BytesIO()
|
402 |
+
fig2.tight_layout()
|
403 |
+
fig2.savefig(buf2, format="png")
|
404 |
+
fig_col2.image(buf2, width = 400) # changed here to fit better
|
405 |
+
else:
|
406 |
+
fig2,ax2 = plt.subplots(figsize=(4,8)) # this changed
|
407 |
+
extent2 = [bins.min(), bins.max(), 0, len(table.index)]
|
408 |
+
ax2.imshow(table.values, cmap='hot', interpolation='nearest', extent=extent2)
|
409 |
+
ax2.set_yticks(range(len(table.index)))
|
410 |
+
ax2.set_yticklabels(table.index)
|
411 |
+
|
412 |
+
buf2 = BytesIO()
|
413 |
+
fig2.tight_layout()
|
414 |
+
fig2.savefig(buf2, format="png")
|
415 |
+
fig_col2.image(buf2, width = 500) # can mess around with width, figsize/etc
|
416 |
+
|
417 |
+
# THEN: slider for range of student teacher ratios -- do the RANGE slider: https://docs.streamlit.io/develop/api-reference/widgets/st.slider
|
418 |
+
|
419 |
+
# with st.expander('Favorite product by Gender within city'):
|
420 |
+
# column1, column2 = st.columns([3,1])
|
421 |
+
|
422 |
+
# # Allow the user to select a gender.
|
423 |
+
# selected_gender = st.radio('What is your Gender:', df.gender.unique(), index = 0)
|
424 |
+
|
425 |
+
# # Apply gender filter.
|
426 |
+
# gender_product = df[df['gender'] == selected_gender]
|
427 |
+
|
428 |
+
# # Allow the user to select a city.
|
429 |
+
# select_city = column2.selectbox('Select City', df.sort_values('City').City.unique())
|
430 |
+
|
431 |
+
# # Apply city filter
|
432 |
+
# city_gender_product = gender_product[gender_product['City'] == select_city]
|
433 |
+
|
434 |
+
# # Use the city_gender_product dataframe as it has filters for gender and city.
|
435 |
+
# fig = px.histogram(city_gender_product.sort_values('product_line') ,x='product_line', y='gross_income', color = 'product_line',)
|
436 |
+
|
437 |
+
# if selected_gender == 'Male':
|
438 |
+
# st.write('What men buy most!')
|
439 |
+
# else:
|
440 |
+
# st.write('What female buy most!')
|
441 |
+
|
442 |
+
# st.plotly_chart(fig, use_container_width=True)
|
443 |
|
444 |
################################################
|
445 |
+
# 5. TODO Multi-page apps (?) this might be for next week/extra
|
446 |
################################################
|