Streamlit для создания интерактивных веб-приложений: начало

Веб-приложения  —  один из самых удобных способов представить результаты работы в сфере науки о данных. Но многих специалистов по данным, не имеющих какого-либо опыта веб-разработки, отпугивает идея создания подобных приложений. Однако с помощью превосходного фреймворка Streamlit можно легко справиться с этой задачей при условии, что вы владеете Python. Ведь Streamlit изначально устроен выполнять самую сложную работу по созданию и компоновке веб-элементов, позволяя нам заниматься только данными.

Для установки фреймворка воспользуемся инструментом pip:

pip install streamlit

После этого можем проверить его версию:

streamlit --version

Если вы все сделали правильно, то с помощью нижеследующей команды можете запустить демонстрационное приложение, которое покажет разные возможности, предоставляемые Streamlit:

streamlit hello

В этом приложении вы найдете широкий спектр классных функциональностей, поддерживаемых фреймворком, которые так необходимы специалистам по данным. Материал данной статьи представляет собой краткий обучающий курс по первоосновам работы со Streamlit. Владея Python, вы буквально за несколько часов разберетесь в сути работы этого инструмента. 

Если по ходу изучения материала вы захотите попрактиковаться, то скрипт предоставлен на этой странице GitHub. В статье мы задействуем датасет Titanic для демонстрации ряда стандартных техник Streamlit с акцентом на интерактивные виджеты.

По возможности будем интегрировать дополнительные виджеты для расширения наших знаний. 

Настройка проекта 

В сущности, каждое веб-приложение Streamlit  —  это скрипт Python. Поверх файла мы импортируем необходимые зависимости. В данном случае потребуется несколько модулей, как показано ниже: 

import pandas as pd
import time
import streamlit as st
import plotly.express as px

Что касается датасета, скачиваем из интернета Titanic. 

@st.cache
def load_dataset(data_link):
    dataset = pd.read_csv(data_link)
    return dataset


titanic_link = 'https://raw.githubusercontent.com/mwaskom/seaborn-data/master/titanic.csv'
titanic_data = load_dataset(titanic_link)

Одной примечательной особенностью является декоратор st.cache, увеличивающий отзывчивость приложения благодаря кэшированию полученных ранее данных. В нашем примере датасет Titanic будет получен лишь один раз, и при последующих обновлениях веб-страницы повторяться эта операция уже не будет. Также стоит отметить, что при любом изменении в коде скрипт будет выполняться заново, поэтому так важно использовать кэширование для улучшения пользовательского опыта.

Для просмотра данных просто выполняем st.dataframe(titanic_data):

Обзор данных 

1. Организационные компоненты (например заголовки) 

Streamlit предлагает несколько способов размещения заголовков на веб-странице. Если нужно присвоить название  —  выполняем st.title(“My First Streamlit App”).

А с помощью st.header() и st.subheader() можно добавить дополнительные заголовки на двух разных уровнях.

Возможен вариант с применением функциональности Markdown для размещения таких заголовков, как st.markdown(“#Just like a header”) и st.markdown(“#Just like a subheader”).

Помимо этого важной организационной составляющей в Streamlit является боковая панель, куда вносятся элементы конфигурации, изменяющие компоненты на главной странице. Просто добавляем в код st.sidebar —  и боковая панель в нашем распоряжении. Примечательно то, что вам несомненно захочется дополнить ее еще большим числом элементов. В связи с этим вместо того, чтобы обращаться к боковой панели посредством st.sidebar, лучше создать на нее ссылку наподобие sidebar = st.sidebar.

2. Виджеты с множественным выбором 

Для сбора ответов пользователей существует несколько вариантов создания виджетов с множественным выбором. Первый из них известен как переключатель:

selected_class = st.radio("Select Class", titanic_data['class'].unique())
st.write("Selected Class:", selected_class)
st.write("Selected Class Type:", type(selected_class))

В результате вы увидите нечто подобное. Обратите внимание, что выбираться будет фактическое значение отображаемого варианта, а не его порядковый индекс. В данном случае это будет текст:

Выбор варианта с помощью радиокнопки

Второй виджет, selectbox, предоставляет выпадающий список с возможность выбора из него. Его код будет вот таким: 

selected_sex = st.selectbox("Select Sex", titanic_data['sex'].unique())
st.write(f"Selected Option: {selected_sex!r}")

Взаимодействие происходит следующим образом: 

Поле выбора с предлагаемыми вариантами 

В том случае, когда пользователю необходимо ввести несколько выбранных вариантов, используйте виджет multiselect, как показано ниже: 

selected_decks = st.multiselect("Select Decks", titanic_data['deck'].unique())
st.write("Selected Decks:", selected_decks)

Пример подобного виджета: 

Виджет с множественным выбором 

3. Числовые виджеты 

Когда в качестве входных данных требуется ввести числа, воспользуйтесь виджетом number_input. Как обычно, можно присвоить виджету имя и установить его значение. Ниже представлен соответствующий код: 

age_columns = st.beta_columns(2)
age_min = age_columns[0].number_input("Minimum Age", value=titanic_data['age'].min())
age_max = age_columns[1].number_input("Maximum Age", value=titanic_data['age'].max())
if age_max < age_min:
    st.error("The maximum age can't be smaller than the minimum age!")
else:
    st.success("Congratulations! Correct Parameters!")
    subset_age = titanic_data[(titanic_data['age'] <= age_max) & (age_min <= titanic_data['age'])]
    st.write(f"Number of Records With Age Between {age_min} and {age_max}: {subset_age.shape[0]}")

Код также содержит такую функциональность Streamlit, как “уведомление”. Для отображения сообщения об ошибке служит st.error(), а st.success() показывает, что задание выполнено успешно. В коде предусмотрена еще одна функциональность  —  столбцы (st.beta_columns), которая применяется при наличии параллельных виджетов, тесно связанных друг с другом. В такой ситуации целесообразно сгруппировать два виджета, которые принимают минимальный и максимальный возраст.

Результатом выполнения кода является следующий виджет: 

Числовой ввод 

Помимо этого виджета Streamlit также предоставляет ползунок (slider), позволяющий пользователю устанавливать числовой ввод без набора каких-либо данных. Смотрим код: 

optionals = st.beta_expander("Optional Configurations", True)
fare_min = optionals.slider(
    "Minimum Fare",
    min_value=float(titanic_data['fare'].min()),
    max_value=float(titanic_data['fare'].max())
)
fare_max = optionals.slider(
    "Maximum Fare",
    min_value=float(titanic_data['fare'].min()),
    max_value=float(titanic_data['fare'].max())
)
subset_fare = titanic_data[(titanic_data['fare'] <= fare_max) & (fare_min <= titanic_data['fare'])]
st.write(f"Number of Records With Fare Between {fare_min} and {fare_max}: {subset_fare.shape[0]}")

С помощью slider вы задаете имя виджета и одновременно устанавливаете минимальные и максимальные значения. Помимо ползунка вышепредставленный код включает еще одну функциональность под названием расширитель (expander)  —  st.beta_expander, которая скрывает дополнительные виджеты. Можно установить расширитель так, чтобы он находился в развернутом виде по умолчанию. 

На следующем изображении представлен интерактивный виджет “ползунок” в сочетании с расширителем:

4. Текстовые виджеты 

Для ввода текстовых данных применяются виджеты text_input и text_area. Главное их отличие состоит в том, что первый лучше подходит для короткой текстовой строки, а второй  —  для большого объема текстовых данных. Виджеты для ввода текста: 

with st.echo("below"):
    balloons = st.text_input("Please enter awesome to see some balloons")
    if balloons == "awesome":
        st.balloons()

st.write("This is a large text area.")
st.text_area("A very big area", height=300)

Данный код показывает, как отображать эти виджеты. В него также были включены две дополнительные функциональности. Первая  —  это виджет (st.echo), дополнительно отображающий код, который содержится в инструкции with. Вторая  —  это “пасхалка”, запускающая воздушные шарики (st.balloons), как показано ниже: 

5. Остальные возможности 

Индикатор выполнения

В тех случаях, когда приложение работает с большими объемами данных, и время ожидания превосходит расчеты пользователя, то лучше снабдить его индикатором выполнения. Рассмотрим код: 

progress_bar = st.progress(0)
progress_text = st.empty()
for i in range(101):
    time.sleep(0.1)
    progress_bar.progress(i)
    progress_text.text(f"Progress: {i}%")

В приложении индикатор выполнения выглядит следующим образом: 

Markdown

Streamlit поддерживает записи Markdown, открывая для нас несметные возможности с помощью st.markdown. На GitHub вы найдете больше информации о его синтаксисе.

Перед вами несколько распространенных примеров: 

Графики  

Если приложение подразумевает показ графиков, то Streamlit нативно поддерживает множество их сторонних вариаций. Ниже приводится перечень из его официальной документации:

write(mpl_fig): отображает график Matplotlib. 
write(altair): отображает график Altair.
write(graphviz): отображает граф Graphviz.
write(plotly_fig): отображает график Plotly.
write(bokeh_fig): отображает график Bokeh.

На следующем изображении представлена гистограмма, выполненная с помощью Plotly:

Заключение

В данной статье были рассмотрены полезные функциональности, которые обязательно должны быть в вашем интерактивном веб-приложении. Как вы уже убедились, Streamlit предоставляет самые разные из них: одни позволяют вводить числа и текст, другие  —  делать множественный выбор, третьи  —  отображать код, Markdown и графические изображения. Этот фреймворк берет на себя все заботы о веб-элементах, позволяя вам сосредоточиться на создании контента приложения. 

Читайте также:

Читайте нас в Telegram, VK и Яндекс.Дзен


Перевод статьи Yong Cui: Build Your First Interactive Data Science Web App with Streamlit

Предыдущая статьяПуть программиста-самоучки: преимущества и подводные камни
Следующая статьяВсё, что должен знать разработчик ПО о качестве кода