mahmoud / awesome-python-applications

💿 Free software that works great, and also happens to be open-source Python.
ftp://you:relookin@it#readme
16.79k stars 2.68k forks source link

Add Project: awesome-streamlit #107

Open MarcSkovMadsen opened 5 years ago

MarcSkovMadsen commented 5 years ago

Basic info

Application name: Awesome Streamlit Application repo link: https://github.com/marcskovmadsen/awesome-streamlit Application home link: https://awesome-streamlit.org/ Application Docs: https://awesome-streamlit.readthedocs.io/ Application Docker Image: https://cloud.docker.com/u/marcskovmadsen/repository/docker/marcskovmadsen/awesome-streamlit Application Package: https://pypi.org/project/streamlit/ Application description:

The purpose of the Awesome Streamlit Application is to share knowledge on how Awesome Streamlit is and can become as a technology for building (data) applications in Python.

This application provides

Animation

Qualifications

The application and repo is new. But the reason why I believe this application is important is because it is the first application to take advantage of the Streamlit framework which has the potential to significantly lower the friction required to develop (applications) in Python.

It's so easy and awesome. See this 4 minute introduction to Streamlit

Introduction to Streamlit

I believe the Streamlit Technology will foster a flood of awesome (micro) apps in Python. So the Streamlit technology is important to your list :-)

The application and repo already provides and will provide tons on information on how to develop, test, build and release these types of applications.

If you have helpfull helps or suggestions feel free to add them to the comments

Best regards and thanks.

Marc

MarcSkovMadsen commented 5 years ago

I'm just listening to the awesome "Talk Python Podcast" where you are joking about "let's be realistic. You will need html and javascript until they put Python in the browser".

That is no longer true. Streamlit solves this using very efficient caching and communication protocols. And it's very, very performant. They just neeed some more components, style and layout options. But that will come. It's a game changer for web development in Python. I believe :-) And please challenge me :-)

Please checkout the application at

https://awesome-streamlit.org/

MarcSkovMadsen commented 5 years ago

https://awesome-streamlit.org/

image

MarcSkovMadsen commented 5 years ago

image

MarcSkovMadsen commented 5 years ago

And the source code for the Spreadsheet gallery example is

"""Page to show that its really easy to create a Spreadsheet like application"""
import pandas as pd
import streamlit as st

@st.cache
def get_biostats_data(url) -> pd.DataFrame:
    """A DataFrame of data from https://people.sc.fsu.edu/~jburkardt/data/csv/biostats.csv

    Returns:
        pd.DataFrame -- [description]
    """
    data = pd.read_csv(url)
    columns = {
        "Name": "Name",
        '     "Sex"': "Sex",
        ' "Age"': "Age",
        ' "Height (in)"': "Height (in)",
        ' "Weight (lbs)"': "Weight (lbs)",
    }
    data = data.rename(columns=columns)
    return data

@st.cache
def transform_biostats_data(source_data: pd.DataFrame) -> pd.DataFrame:
    return source_data

@st.cache
def get_grades_data(url: str) -> pd.DataFrame:
    source_data = pd.read_csv(source_url)
    columns = {
        "Last name": "Last name",
        ' "First name"': "First name",
        ' "SSN"': "SSN",
        '        "Test1"': "Test1",
        ' "Test2"': "Test2",
        ' "Test3"': "Test3",
        ' "Test4"': "Test4",
        ' "Final"': "Final",
        ' "Grade"': "Grade",
    }
    source_data = source_data.rename(columns=columns)
    source_data["Test1"] = pd.to_numeric(source_data["Test1"], errors="coerce")
    source_data["First name"] = source_data["First name"].str.replace('"', "")
    return source_data

@st.cache
def transform_grades_data(source_data: pd.DataFrame) -> pd.DataFrame:
    # Add formulas
    transform_data = source_data.copy()
    transform_data["Test Mean"] = (
        transform_data[["Test1", "Test2", "Test3", "Test4"]].mean(axis=1).round()
    )
    transform_data["Relative diff from 1 to 4 (%)"] = (
        (transform_data["Test4"] - transform_data["Test1"])
        / transform_data["Test1"]
        * 100
    ).round()
    return transform_data

st.markdown(
    """
This app illustrates that it's so easy to create high quality spreadsheet like apps
 with [Streamlit](https://streamlit.io). You can **change the sheet** or **hide/show**
 the source data via the sidebar!"""
)

st.sidebar.title("Spreadsheet")
sheet = st.sidebar.selectbox("Select Sheet", ["Biostats", "Grades"])
show_source_data = st.sidebar.checkbox("Show Source Data", value=True)

st.write(f"""## {sheet}""")

if sheet == "Biostats":
    with st.spinner("Loading source data ..."):
        source_url = "https://people.sc.fsu.edu/~jburkardt/data/csv/biostats.csv"
        source_data = get_biostats_data(source_url)
        transform_data = transform_biostats_data(source_data)
        measures = ["Age", "Height (in)", "Weight (lbs)"]

    # Show
    measure = st.selectbox("Measure", ["Age", "Height (in)", "Weight (lbs)"])
    with st.spinner("Updating plot ..."):
        selected = pd.DataFrame(transform_data[measure])
        st.bar_chart(selected)

elif sheet == "Grades":
    with st.spinner("Loading source data ..."):
        source_url = "https://people.sc.fsu.edu/~jburkardt/data/csv/grades.csv"
        source_data = get_grades_data(source_url)
        transform_data = transform_grades_data(source_data)

    # Show
    st.write(  # pylint-disable=line-too-long
        "I illustrate a calculation by calculating the Test Mean."
        " After that we illustrate a calculation to show how much better the students did"
        " the 4th test compared to 1st one.",
        transform_data[
            [
                "First name",
                "Last name",
                "Test1",
                "Test2",
                "Test3",
                "Test4",
                "Test Mean",
                "Relative diff from 1 to 4 (%)",
            ]
        ],
    )
# Show Soure
if show_source_data:
    st.subheader("Source Data")
    st.markdown(f"[{source_url}]({source_url})")
    st.dataframe(source_data)
MarcSkovMadsen commented 5 years ago

Ines Montani the author behind Spacy put out this one

image

and the code is

import streamlit as st
import spacy
from spacy import displacy
import pandas as pd

SPACY_MODEL_NAMES = ["en_core_web_sm", "en_core_web_md", "de_core_news_sm"]
DEFAULT_TEXT = "Mark Zuckerberg is the CEO of Facebook."
HTML_WRAPPER = """<div style="overflow-x: auto; border: 1px solid #e6e9ef; border-radius: 0.25rem; padding: 1rem; margin-bottom: 2.5rem">{}</div>"""

@st.cache(ignore_hash=True)
def load_model(name):
    return spacy.load(name)

@st.cache(ignore_hash=True)
def process_text(model_name, text):
    nlp = load_model(model_name)
    return nlp(text)

st.sidebar.title("Interactive spaCy visualizer")
st.sidebar.markdown(
    """
Process text with [spaCy](https://spacy.io) models and visualize named entities,
dependencies and more. Uses spaCy's built-in
[displaCy](http://spacy.io/usage/visualizers) visualizer under the hood.
"""
)

spacy_model = st.sidebar.selectbox("Model name", SPACY_MODEL_NAMES)
model_load_state = st.info(f"Loading model '{spacy_model}'...")
nlp = load_model(spacy_model)
model_load_state.empty()

text = st.text_area("Text to analyze", DEFAULT_TEXT)
doc = process_text(spacy_model, text)

if "parser" in nlp.pipe_names:
    st.header("Dependency Parse & Part-of-speech tags")
    st.sidebar.header("Dependency Parse")
    split_sents = st.sidebar.checkbox("Split sentences", value=True)
    collapse_punct = st.sidebar.checkbox("Collapse punctuation", value=True)
    collapse_phrases = st.sidebar.checkbox("Collapse phrases")
    compact = st.sidebar.checkbox("Compact mode")
    options = {
        "collapse_punct": collapse_punct,
        "collapse_phrases": collapse_phrases,
        "compact": compact,
    }
    docs = [span.as_doc() for span in doc.sents] if split_sents else [doc]
    for sent in docs:
        html = displacy.render(sent, options=options)
        # Double newlines seem to mess with the rendering
        html = html.replace("\n\n", "\n")
        if split_sents and len(docs) > 1:
            st.markdown(f"> {sent.text}")
        st.write(HTML_WRAPPER.format(html), unsafe_allow_html=True)

if "ner" in nlp.pipe_names:
    st.header("Named Entities")
    st.sidebar.header("Named Entities")
    default_labels = ["PERSON", "ORG", "GPE", "LOC"]
    labels = st.sidebar.multiselect(
        "Entity labels", nlp.get_pipe("ner").labels, default_labels
    )
    html = displacy.render(doc, style="ent", options={"ents": labels})
    # Newlines seem to mess with the rendering
    html = html.replace("\n", " ")
    st.write(HTML_WRAPPER.format(html), unsafe_allow_html=True)
    attrs = ["text", "label_", "start", "end", "start_char", "end_char"]
    if "entity_linker" in nlp.pipe_names:
        attrs.append("kb_id_")
    data = [
        [str(getattr(ent, attr)) for attr in attrs]
        for ent in doc.ents
        if ent.label_ in labels
    ]
    df = pd.DataFrame(data, columns=attrs)
    st.dataframe(df)

if "textcat" in nlp.pipe_names:
    st.header("Text Classification")
    st.markdown(f"> {text}")
    df = pd.DataFrame(doc.cats.items(), columns=("Label", "Score"))
    st.dataframe(df)

vector_size = nlp.meta.get("vectors", {}).get("width", 0)
if vector_size:
    st.header("Vectors & Similarity")
    st.code(nlp.meta["vectors"])
    text1 = st.text_input("Text or word 1", "apple")
    text2 = st.text_input("Text or word 2", "orange")
    doc1 = process_text(spacy_model, text1)
    doc2 = process_text(spacy_model, text2)
    similarity = doc1.similarity(doc2)
    if similarity > 0.5:
        st.success(similarity)
    else:
        st.error(similarity)

st.header("Token attributes")

if st.button("Show token attributes"):
    attrs = [
        "idx",
        "text",
        "lemma_",
        "pos_",
        "tag_",
        "dep_",
        "head",
        "ent_type_",
        "ent_iob_",
        "shape_",
        "is_alpha",
        "is_ascii",
        "is_digit",
        "is_punct",
        "like_num",
    ]
    data = [[str(getattr(token, attr)) for attr in attrs] for token in doc]
    df = pd.DataFrame(data, columns=attrs)
    st.dataframe(df)

st.header("JSON Doc")
if st.button("Show JSON Doc"):
    st.json(doc.to_json())

st.header("JSON model meta")
if st.button("Show JSON model meta"):
    st.json(nlp.meta)
mahmoud commented 5 years ago

Very interesting! Certainly seems like a new class of application is emerging. For the record, it still uses js/typescript, but it's great that the application developer doesn't have to write it themselves. I'll have to take a bit of time to evaluate this new approach, especially as it's still emerging. Thanks for bringing it to my attention!

treuille commented 5 years ago

As the admittedly biased co-creator of Streamlit. I agree that would be totally awesome to include awesome streamlit in awesome python. What could be more meta? Or more awesome? Or more pythonic? ;-)

Seriously though, please let me know if I can answer any questions or in any way help this effort!

MarcSkovMadsen commented 5 years ago

Thanks @mahmoud . Yes it definately uses js/ typescript :-) But let the really skilled front end developers do that. They can develop general web components to be used by Streamlit. And let the rest of us from hobbyist to rockstar pythonista get our things done.

I've updated the first post above with a video animation and an image of the youtube video because I think they are awesome.

I know that you might not think awesome-streamlit.org is awesome (enough yet :-)). But I believe Streamlit is or could be a game changer for awesome python apps in general.

Have a nice weekend.