Streamlit для аналитика: data apps за час
Зачем аналитику Streamlit
У аналитика регулярно возникает ситуация: есть Python-скрипт с интересным анализом, но показать его бизнесу — проблема. Jupyter notebook менеджер не откроет, dashboard в Tableau долго делать, frontend-разработчик занят.
Streamlit решает эту задачу. За час вы превращаете Python-скрипт в интерактивное web-приложение, которое можно открыть в браузере и показать команде. Без HTML, CSS, JavaScript. Только Python.
Типовые use-cases: интерактивный calculator ROI, дашборд с фильтрами для специфической задачи, демо ML-модели для PM, sharing аналитических insights вне Tableau/Metabase.
Минимальный пример
Установка:
pip install streamlitСкрипт app.py:
import streamlit as st
import pandas as pd
st.title('Анализ продаж')
# Загружаем данные
df = pd.read_csv('sales.csv')
st.write(f'Всего записей: {len(df)}')
st.dataframe(df.head(10))
# График
st.bar_chart(df.groupby('category')['amount'].sum())Запуск:
streamlit run app.pyОткрывается браузер с локальным приложением. Три строки кода — interactive app с таблицей и графиком.
Виджеты для интерактивности
Главная ценность Streamlit — простые виджеты для взаимодействия:
import streamlit as st
import pandas as pd
df = pd.read_csv('sales.csv')
# Выбор категории
category = st.selectbox('Категория', df['category'].unique())
# Диапазон дат
date_range = st.date_input('Период', [df['date'].min(), df['date'].max()])
# Чекбокс
show_refunded = st.checkbox('Включить возвраты', value=False)
# Слайдер
min_amount = st.slider('Минимальная сумма', 0, 10000, 100)
# Фильтрация
filtered = df[
(df['category'] == category) &
(df['date'] >= date_range[0]) & (df['date'] <= date_range[1]) &
(df['amount'] >= min_amount)
]
if not show_refunded:
filtered = filtered[filtered['status'] != 'refunded']
st.write(f'Найдено {len(filtered)} записей на {filtered["amount"].sum():,.0f} руб')
st.dataframe(filtered)Виджеты обновляются реактивно: пользователь меняет значение → скрипт перезапускается → приложение отрисовывается заново. Для аналитика это невероятно удобно — сложная логика фильтрации в 10 строк.
Графики
Streamlit умеет рендерить plotly, matplotlib, seaborn, altair:
import plotly.express as px
fig = px.line(daily_data, x='date', y='revenue', color='region')
st.plotly_chart(fig)Для простых случаев — встроенные команды:
st.line_chart(df[['revenue']])
st.bar_chart(df.groupby('day')['orders'].sum())
st.area_chart(df[['new_users', 'returning_users']])Этого хватает для 80% дашбордов.
Layout
Виджеты можно располагать в колонках и вкладках:
col1, col2, col3 = st.columns(3)
col1.metric('Revenue', '₽1.2M', '+12%')
col2.metric('Orders', '4,567', '+8%')
col3.metric('AOV', '₽263', '-3%')
tab1, tab2, tab3 = st.tabs(['Overview', 'Sales', 'Customers'])
with tab1:
st.write('Обзор бизнеса')
st.line_chart(...)
with tab2:
st.write('Детали продаж')
st.bar_chart(...)
with tab3:
st.write('Клиенты')
st.dataframe(...)Это даёт профессионально выглядящий дашборд без HTML.
Кэширование
Для медленных операций (тяжёлые SQL, скачивание файлов) — декоратор @st.cache_data:
@st.cache_data
def load_orders():
# Эта функция запустится один раз
return pd.read_sql('SELECT * FROM orders', engine)
df = load_orders() # При повторных запусках скрипта — из кэшаБез кэша скрипт при каждом клике перечитывал бы SQL. С кэшем — только один раз за сессию.
@st.cache_resource — для non-data объектов (соединения с БД, ML-модели):
@st.cache_resource
def load_model():
return joblib.load('model.pkl')
model = load_model()Пример: RFM-дашборд
Реальное применение — интерактивный RFM:
import streamlit as st
import pandas as pd
import plotly.express as px
st.set_page_config(page_title='RFM', layout='wide')
st.title('RFM Analysis')
# Загрузка
@st.cache_data
def load_data():
return pd.read_sql("""
SELECT user_id, created_at, amount FROM orders WHERE status = 'paid'
""", conn)
df = load_data()
# Фильтры в сайдбаре
min_date = st.sidebar.date_input('С даты', df['created_at'].min())
max_date = st.sidebar.date_input('По дату', df['created_at'].max())
df_filtered = df[(df['created_at'] >= min_date) & (df['created_at'] <= max_date)]
# Расчёт RFM
rfm = df_filtered.groupby('user_id').agg(
recency=('created_at', lambda x: (pd.Timestamp.now() - x.max()).days),
frequency=('user_id', 'count'),
monetary=('amount', 'sum')
).reset_index()
# Quantiles
rfm['R_score'] = pd.qcut(rfm['recency'], 5, labels=[5,4,3,2,1])
rfm['F_score'] = pd.qcut(rfm['frequency'], 5, labels=[1,2,3,4,5])
rfm['M_score'] = pd.qcut(rfm['monetary'], 5, labels=[1,2,3,4,5])
rfm['RFM'] = rfm['R_score'].astype(str) + rfm['F_score'].astype(str) + rfm['M_score'].astype(str)
# Визуализация
col1, col2 = st.columns(2)
with col1:
st.metric('Total customers', len(rfm))
st.metric('Avg monetary', f'{rfm["monetary"].mean():,.0f}')
with col2:
fig = px.scatter(rfm, x='frequency', y='monetary', color='R_score',
title='Frequency vs Monetary')
st.plotly_chart(fig)
# Сегменты
st.subheader('Топ-10 VIP')
st.dataframe(rfm.nlargest(10, 'monetary'))Час работы — полноценный interactive dashboard. Бизнес может крутить фильтры, смотреть данные, находить insights.
Разбираться с быстрыми инструментами для прототипирования — полезная часть senior-работы. В тренажёре Карьерник есть Python-задачи для аналитика, включая работу с инструментами data-сообщества.
Deployment
Локально streamlit запускается через streamlit run app.py. Для sharing с командой — несколько вариантов:
Streamlit Community Cloud — бесплатный хостинг, нужен git-репозиторий. Деплой за минуту, public URL.
Hugging Face Spaces — бесплатно для public приложений, хорошая интеграция с ML-моделями.
Собственный сервер — Docker-контейнер, nginx впереди. Для корпоративного использования.
Streamlit Snowflake — если вы на Snowflake, есть встроенный deployment внутри их платформы.
Аутентификация
По умолчанию Streamlit-apps открыты всем, кто знает URL. Для корпоративного использования нужна защита.
Варианты:
- Streamlit-authenticator — Python-пакет для login/password.
- OAuth через Google/GitHub — через внешние middleware.
- Reverse proxy с basic auth — на уровне инфраструктуры.
- Streamlit Cloud Team — встроенная SSO в платной версии.
Для внутренних демо обычно хватает первых двух.
Когда Streamlit подходит
Идеален для:
Быстрых internal tools — калькуляторы, дашборды для отдельной команды.
Демо ML-моделей — загрузить модель, показать predictions в UI.
Ad-hoc аналитических приложений — когда разовая задача заслуживает интерактивности.
Прототипов — проверить идею UI до того, как отдать frontend-команде.
Когда Streamlit НЕ подходит
Production-приложения с тысячами пользователей. Streamlit однопоточный по natureй, для масштаба нужны Django/FastAPI + React.
Сложные UI с кастомным дизайном. Streamlit — opinionated, стили ограничены.
Приложения с реальным real-time (websocket, chat). Streamlit обновляется по запросу, не streaming.
Mobile-first приложения. Работает на мобильных, но experience не идеальный.
Альтернативы
Gradio — похоже на Streamlit, но больше фокус на ML. Хорошо для модельных демо.
Dash (by Plotly) — больше контроля, сложнее, ближе к fullstack. Для production дашбордов.
Panel — мощнее Streamlit, но learning curve выше.
Voilà — превращает Jupyter notebook в app. Простейший способ, но ограниченный.
Для аналитика самый быстрый вход — Streamlit. Остальное — когда нужно больше.
Читайте также
- Python шпаргалка для аналитика
- Jupyter Notebook: шпаргалка
- Pandas шпаргалка
- Как автоматизировать отчёт в Python
FAQ
Сколько учить?
Базовый уровень — 1-2 дня. Уверенное владение — неделя.
Что быстрее — Streamlit или Tableau?
Streamlit быстрее для прототипов и custom-логики. Tableau быстрее для типовых BI-дашбордов с drag-n-drop.
Можно ли связать с БД?
Да, любым Python-способом: SQLAlchemy, psycopg2, clickhouse-driver. @st.cache_data для кэширования.
Streamlit бесплатный?
Да, open-source. Streamlit Community Cloud для деплоя тоже бесплатный. Платная версия Snowflake Streamlit — только если вы на Snowflake.