Dashboards Interativos com Streamlit

Crie dashboards interativos com Python e Streamlit. Aprenda graficos, filtros, cache, layout e deploy de aplicacoes de dados.

5 min de leitura Equipe Python Brasil

Streamlit transformou a forma como desenvolvedores Python criam aplicacoes de dados. Em vez de aprender HTML, CSS e JavaScript, voce escreve apenas Python e o Streamlit gera uma interface web interativa automaticamente. Neste artigo, vamos construir dashboards profissionais do zero, cobrindo graficos, filtros, cache e deploy.

Instalacao e Primeiro Dashboard

Instale o Streamlit e crie seu primeiro app:

pip install streamlit pandas plotly

Crie um arquivo app.py:

import streamlit as st
import pandas as pd

st.set_page_config(page_title="Dashboard de Vendas", layout="wide")

st.title("Dashboard de Vendas")
st.markdown("Analise completa das vendas da empresa")

# Dados de exemplo
dados = pd.DataFrame({
    "Mes": ["Jan", "Fev", "Mar", "Abr", "Mai", "Jun",
            "Jul", "Ago", "Set", "Out", "Nov", "Dez"],
    "Vendas": [45000, 52000, 48000, 55000, 61000, 58000,
               63000, 67000, 59000, 71000, 75000, 82000],
    "Meta": [50000, 50000, 50000, 55000, 55000, 55000,
             60000, 60000, 60000, 70000, 70000, 70000],
    "Clientes": [120, 135, 128, 142, 156, 149,
                 163, 171, 155, 180, 192, 205],
})

# Metricas no topo
col1, col2, col3, col4 = st.columns(4)
col1.metric("Vendas Totais", f"R$ {dados['Vendas'].sum():,.0f}")
col2.metric("Media Mensal", f"R$ {dados['Vendas'].mean():,.0f}")
col3.metric("Melhor Mes", f"R$ {dados['Vendas'].max():,.0f}")
col4.metric("Total Clientes", f"{dados['Clientes'].sum():,}")

st.dataframe(dados, use_container_width=True)

Execute com:

streamlit run app.py

Graficos Interativos com Plotly

O Streamlit integra nativamente com Plotly para graficos ricos:

import streamlit as st
import pandas as pd
import plotly.express as px
import plotly.graph_objects as go

def criar_grafico_vendas(dados: pd.DataFrame):
    """Grafico de linhas comparando vendas vs meta."""
    fig = go.Figure()

    fig.add_trace(go.Scatter(
        x=dados["Mes"], y=dados["Vendas"],
        mode="lines+markers", name="Vendas",
        line=dict(color="#2E86AB", width=3),
    ))

    fig.add_trace(go.Scatter(
        x=dados["Mes"], y=dados["Meta"],
        mode="lines", name="Meta",
        line=dict(color="#E8443A", width=2, dash="dash"),
    ))

    fig.update_layout(
        title="Vendas vs Meta Mensal",
        xaxis_title="Mes",
        yaxis_title="Valor (R$)",
        height=400,
    )

    return fig

def criar_grafico_barras(dados: pd.DataFrame):
    """Grafico de barras com cores condicionais."""
    cores = ["#2E86AB" if v >= m else "#E8443A"
             for v, m in zip(dados["Vendas"], dados["Meta"])]

    fig = px.bar(
        dados, x="Mes", y="Vendas",
        title="Vendas Mensais (verde = meta batida)",
        color_discrete_sequence=cores,
    )
    fig.update_layout(height=400)
    return fig

# No app principal
st.plotly_chart(criar_grafico_vendas(dados), use_container_width=True)

col_esq, col_dir = st.columns(2)
with col_esq:
    st.plotly_chart(criar_grafico_barras(dados), use_container_width=True)
with col_dir:
    fig_pizza = px.pie(dados, values="Vendas", names="Mes", title="Distribuicao por Mes")
    st.plotly_chart(fig_pizza, use_container_width=True)

Filtros e Interatividade

Adicione filtros para que o usuario explore os dados:

import streamlit as st
import pandas as pd

def dashboard_com_filtros():
    st.sidebar.header("Filtros")

    # Dados completos
    df = carregar_dados()

    # Filtro de periodo
    meses = st.sidebar.multiselect(
        "Selecione os meses",
        options=df["Mes"].unique(),
        default=df["Mes"].unique(),
    )

    # Filtro de valor minimo
    valor_min = st.sidebar.slider(
        "Vendas minimas (R$)",
        min_value=0,
        max_value=100000,
        value=0,
        step=5000,
    )

    # Filtro de regiao
    regioes = st.sidebar.selectbox(
        "Regiao",
        ["Todas", "Sudeste", "Sul", "Nordeste", "Norte", "Centro-Oeste"],
    )

    # Aplicar filtros
    df_filtrado = df[df["Mes"].isin(meses)]
    df_filtrado = df_filtrado[df_filtrado["Vendas"] >= valor_min]
    if regioes != "Todas":
        df_filtrado = df_filtrado[df_filtrado["Regiao"] == regioes]

    # Mostrar resultados filtrados
    st.subheader(f"Resultados: {len(df_filtrado)} registros")
    st.dataframe(df_filtrado, use_container_width=True)

    # Metricas do filtro
    if not df_filtrado.empty:
        col1, col2 = st.columns(2)
        col1.metric("Total Filtrado", f"R$ {df_filtrado['Vendas'].sum():,.0f}")
        col2.metric("Media Filtrada", f"R$ {df_filtrado['Vendas'].mean():,.0f}")

Cache para Performance

O Streamlit reexecuta o script a cada interacao. Use cache para evitar reprocessamento:

import streamlit as st
import pandas as pd
import time

@st.cache_data(ttl=3600)  # Cache por 1 hora
def carregar_dados_csv(caminho: str) -> pd.DataFrame:
    """Carrega dados com cache automatico."""
    df = pd.read_csv(caminho)
    # Processamento pesado
    df["data"] = pd.to_datetime(df["data"])
    df["mes"] = df["data"].dt.month
    df["ano"] = df["data"].dt.year
    return df

@st.cache_resource  # Cache permanente para recursos
def conectar_banco():
    """Conexao com banco de dados (reutilizada entre sessoes)."""
    import sqlalchemy
    engine = sqlalchemy.create_engine("postgresql://user:pass@localhost/db")
    return engine

@st.cache_data
def calcular_metricas(df: pd.DataFrame) -> dict:
    """Calcula metricas agregadas."""
    return {
        "total_vendas": df["valor"].sum(),
        "ticket_medio": df["valor"].mean(),
        "total_clientes": df["cliente_id"].nunique(),
        "crescimento": (
            df[df["ano"] == 2025]["valor"].sum()
            / df[df["ano"] == 2024]["valor"].sum() - 1
        ) * 100,
    }

# Uso
df = carregar_dados_csv("vendas.csv")
metricas = calcular_metricas(df)

st.metric("Total de Vendas", f"R$ {metricas['total_vendas']:,.0f}")
st.metric("Ticket Medio", f"R$ {metricas['ticket_medio']:,.0f}")

Layout Avancado com Multiplas Paginas

Organize dashboards complexos em paginas:

import streamlit as st

# Configuracao da pagina
st.set_page_config(page_title="Analytics", layout="wide")

# Navegacao
pagina = st.sidebar.radio("Navegacao", ["Visao Geral", "Vendas", "Clientes", "Produtos"])

if pagina == "Visao Geral":
    st.header("Visao Geral")
    col1, col2, col3 = st.columns(3)
    col1.metric("Receita", "R$ 756.000", "+12%")
    col2.metric("Clientes Ativos", "1.842", "+8%")
    col3.metric("NPS", "72", "+5")

    # Tabs dentro da pagina
    tab1, tab2 = st.tabs(["Mensal", "Trimestral"])
    with tab1:
        st.write("Dados mensais aqui")
    with tab2:
        st.write("Dados trimestrais aqui")

elif pagina == "Vendas":
    st.header("Analise de Vendas")
    # Upload de arquivo
    arquivo = st.file_uploader("Carregar dados de vendas", type=["csv", "xlsx"])
    if arquivo is not None:
        if arquivo.name.endswith(".csv"):
            df = pd.read_csv(arquivo)
        else:
            df = pd.read_excel(arquivo)
        st.dataframe(df)

elif pagina == "Clientes":
    st.header("Analise de Clientes")
    st.info("Selecione um cliente para ver o historico")

elif pagina == "Produtos":
    st.header("Catalogo de Produtos")
    st.warning("Dados sendo atualizados")

Formularios e Entrada de Dados

O Streamlit tambem serve para criar formularios de entrada:

import streamlit as st

def formulario_cadastro():
    st.subheader("Cadastro de Produto")

    with st.form("form_produto"):
        nome = st.text_input("Nome do Produto")
        categoria = st.selectbox("Categoria", ["Eletronicos", "Roupas", "Alimentos"])
        preco = st.number_input("Preco (R$)", min_value=0.0, step=0.01)
        estoque = st.number_input("Estoque", min_value=0, step=1)
        descricao = st.text_area("Descricao")
        destaque = st.checkbox("Produto em destaque")

        enviado = st.form_submit_button("Cadastrar")

        if enviado:
            if nome and preco > 0:
                st.success(f"Produto '{nome}' cadastrado com sucesso!")
                st.json({
                    "nome": nome,
                    "categoria": categoria,
                    "preco": preco,
                    "estoque": estoque,
                    "destaque": destaque,
                })
            else:
                st.error("Preencha todos os campos obrigatorios.")

Deploy do Dashboard

Para disponibilizar seu dashboard, o Streamlit Community Cloud e a opcao mais simples:

# requirements.txt
streamlit==1.32.0
pandas==2.2.0
plotly==5.18.0

Basta conectar seu repositorio GitHub ao Streamlit Cloud e o deploy e automatico. Para ambientes corporativos, use Docker:

FROM python:3.12-slim
WORKDIR /app
COPY requirements.txt .
RUN pip install -r requirements.txt
COPY . .
EXPOSE 8501
CMD ["streamlit", "run", "app.py", "--server.port=8501"]

Boas Praticas

Mantenha o processamento pesado fora do fluxo principal usando cache. Organize o codigo em funcoes reutilizaveis. Use st.spinner() para indicar carregamento em operacoes lentas. Teste o dashboard com diferentes tamanhos de tela, ja que o Streamlit e responsivo por padrao. E sempre valide entradas do usuario antes de processar dados.

Conclusao

Streamlit democratiza a criacao de dashboards em Python. Sem necessidade de conhecer frontend, voce constroi aplicacoes de dados interativas e visualmente atrativas. Com cache, filtros e integracao com Plotly, e possivel criar dashboards que atendem desde analises exploratórias ate paineis de producao. Comece com um dashboard simples e evolua conforme as necessidades do seu projeto.

E

Equipe Python Brasil

Contribuidor do Python Brasil — Aprenda Python em Português