diff --git a/Procfile b/Procfile index ec4a45e..6b888ae 100644 --- a/Procfile +++ b/Procfile @@ -1 +1 @@ -web: sh setup.sh && streamlit run beta_distribution.py +web: sh setup.sh && streamlit run st_runner.py apps diff --git a/beta_distribution.py b/apps/beta_distribution.py similarity index 96% rename from beta_distribution.py rename to apps/beta_distribution.py index 685e07b..0654e17 100644 --- a/beta_distribution.py +++ b/apps/beta_distribution.py @@ -1,8 +1,11 @@ import streamlit as st -from scipy.stats import beta, norm +from scipy.stats import beta import numpy as np import matplotlib.pyplot as plt +import hvplot.pandas # noqa: F401 +import holoviews as hv +hv.extension("bokeh") st.header("Beta Distribution Tutorial") @@ -122,7 +125,8 @@ that best explain these three data points? The best ratio of alpha to beta is probably around 1:6. However, is it 1:6, or is it 6:36, or is it 15:90? -Play around with different ratios to see which one maximizes the log likelihood. +Play around with different ratios +to see which one maximizes the log likelihood. """ ) @@ -277,7 +281,7 @@ def process_data(data): # This is done by capturing the output of stdout and surfacing it to HTML. try: data = np.array([float(i) for i in data.split(", ")]) - except ValueError as e: + except ValueError: raise ValueError("The data that you input must be castable as floats!") if not (np.all(data > 0) and np.all(data < 1)): raise ValueError("Your input data must be 0 < x < 1.") @@ -300,7 +304,8 @@ Did you like this mini-tutorial? If you did, please give it a star on [GitHub](https://github.com/ericmjl/minimal-streamlit-example). -This was hand-crafted using streamlit in under 3 hours. +This was hand-crafted using streamlit in under 3 hours, +2.5 of which were spent crafting prose. Created by [Eric J. Ma](https://ericmjl.github.io). """ diff --git a/apps/iris.py b/apps/iris.py new file mode 100644 index 0000000..205c65b --- /dev/null +++ b/apps/iris.py @@ -0,0 +1,27 @@ +from sklearn.datasets import load_iris +import pandas as pd +import streamlit as st +import holoviews as hv +import hvplot.pandas # noqa: F401 + + +st.header("Holoviews!") +st.write("As a bonus, I'm going to show you a holoviews plot in streamlit!") + + +def iris_data(): + data = load_iris() + df = pd.DataFrame(data["data"], columns=data["feature_names"]) + return df + + +df = iris_data() + +x_column = st.selectbox("X axis", df.columns) +y_column = st.selectbox("Y axis", df.columns) + +plot = ( + iris_data().hvplot.scatter(x_column, y_column).opts(width=400, height=400) +) + +st.bokeh_chart(hv.render(plot, backend="bokeh")) diff --git a/environment.yml b/environment.yml index f84be43..c059ff2 100644 --- a/environment.yml +++ b/environment.yml @@ -16,5 +16,7 @@ dependencies: - pydocstyle - flake8 - black +- hvplot +- bokeh - pip: - streamlit diff --git a/st_runner.py b/st_runner.py new file mode 100644 index 0000000..d24abb6 --- /dev/null +++ b/st_runner.py @@ -0,0 +1,51 @@ +import streamlit as st +import os +import sys +import importlib.util + +# Parse command-line arguments. +if len(sys.argv) > 1: + folder = os.path.abspath(sys.argv[1]) +else: + folder = os.path.abspath(os.getcwd()) + +# Get filenames for all files in this path, excluding this script. + +this_file = os.path.abspath(__file__) +fnames = [] + +for basename in os.listdir(folder): + fname = os.path.join(folder, basename) + + if fname.endswith(".py") and fname != this_file: + fnames.append(fname) + +# Make a UI to run different files. +files = {f.split("/")[-1].split(".")[0]: f for f in fnames} +filename = st.sidebar.selectbox("Select an app", list(files.keys())) +fname_to_run = files[filename] + +# Create module from filepath and put in sys.modules, so Streamlit knows +# to watch it for changes. + +fake_module_count = 0 + + +def load_module(filepath): + global fake_module_count + + modulename = "_dont_care_%s" % fake_module_count + spec = importlib.util.spec_from_file_location(modulename, filepath) + module = importlib.util.module_from_spec(spec) + sys.modules[modulename] = module + + fake_module_count += 1 + + +# Run the selected file. + +with open(fname_to_run) as f: + load_module(fname_to_run) + filebody = f.read() + +exec(filebody, {})