Guia

Dashboard com Streamlit para relatórios em Python

Aprenda a criar um dashboard com Streamlit e Python para transformar CSV em relatório interativo com filtros, métricas, gráficos e exportação.

6 min de leitura

Dashboard é um dos projetos de Python mais fáceis de explicar em entrevista porque resolve um problema que quase toda empresa conhece: transformar planilhas, CSVs e indicadores soltos em uma tela que alguém consegue usar para decidir. Para quem está buscando vaga júnior, estágio, freelance ou transição para dados, um painel simples com filtros, métricas e gráficos costuma comunicar mais valor do que um notebook cheio de células sem contexto.

O Streamlit é uma biblioteca Python feita para criar aplicações de dados com pouco código. Você escreve o fluxo em Python, usa pandas para preparar os dados e o próprio Streamlit cuida da interface web. Não substitui Power BI, Tableau ou Looker em todos os cenários corporativos, mas é excelente para protótipos, relatórios internos, provas de conceito, painéis operacionais e projetos de portfólio.

Neste guia, vamos montar um dashboard de vendas fictícias com upload de CSV, filtros por período e categoria, KPIs, gráfico de receita mensal e exportação da base filtrada. Se você ainda está consolidando pandas, leia também Análise de dados com pandas e pandas no glossário. Para transformar o projeto em material de carreira, combine com projetos de portfólio Python e currículo Python para vaga júnior. Se o seu time também trabalha com Go para serviços de backend, vale comparar depois com conteúdos de arquitetura em Golang Brasil.

Quando usar Streamlit

Use Streamlit quando a prioridade é colocar uma análise nas mãos de alguém rapidamente. Alguns casos bons:

  • painel de vendas para acompanhar receita, ticket médio e pedidos;
  • dashboard financeiro para conciliação, despesas ou inadimplência;
  • relatório de marketing com origem de leads, campanha e conversão;
  • protótipo de produto de dados antes de investir em frontend completo;
  • ferramenta interna para operação filtrar filas, exceções e alertas;
  • apresentação de projeto de portfólio com dados reais ou anonimizados.

Evite Streamlit quando você precisa de controle fino de permissões, centenas de usuários simultâneos, governança corporativa de BI ou experiência visual altamente customizada. Nesses casos, ele pode continuar útil como protótipo, mas a versão final talvez precise de FastAPI, banco de dados, autenticação e frontend dedicado.

Estrutura do projeto

Crie uma pasta simples:

dashboard-vendas/
  app.py
  dados_exemplo.csv
  requirements.txt
  README.md

Instale as dependências em um ambiente virtual:

python -m venv .venv
source .venv/bin/activate
pip install streamlit pandas plotly
pip freeze > requirements.txt

Em Windows, a ativação costuma ser:

.venv\Scripts\activate

O arquivo requirements.txt ajuda quem for avaliar seu projeto a rodar tudo sem adivinhar versões. No README, explique o problema de negócio, a origem dos dados, como executar e quais decisões o dashboard ajuda a tomar.

CSV de exemplo

Use dados fictícios com colunas claras. Um arquivo dados_exemplo.csv pode começar assim:

data,categoria,canal,pedidos,receita
2026-01-05,Cursos,Orgânico,18,4320.50
2026-01-12,Consultoria,Indicação,4,7200.00
2026-02-03,Cursos,Anúncios,27,6840.90
2026-02-18,Assinatura,Orgânico,35,3150.00
2026-03-07,Consultoria,Orgânico,6,10800.00

Para portfólio público, nunca suba dados pessoais, contratos reais, chaves de API, nomes de clientes ou planilhas internas da empresa. Se você quer demonstrar um caso parecido com trabalho real, anonimize tudo e deixe isso explícito.

Primeiro app Streamlit

Crie app.py:

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


st.set_page_config(
    page_title="Dashboard de vendas",
    page_icon=None,
    layout="wide",
)

st.title("Dashboard de vendas com Python")
st.write("Acompanhe receita, pedidos e ticket médio por período, categoria e canal.")

arquivo = st.file_uploader("Envie um CSV de vendas", type=["csv"])

if arquivo is None:
    st.info("Envie um arquivo CSV ou use dados_exemplo.csv para testar o painel.")
    st.stop()

df = pd.read_csv(arquivo)
df["data"] = pd.to_datetime(df["data"])
df["receita"] = pd.to_numeric(df["receita"], errors="coerce")
df["pedidos"] = pd.to_numeric(df["pedidos"], errors="coerce")
df = df.dropna(subset=["data", "receita", "pedidos"])

Rode com:

streamlit run app.py

O navegador abrirá uma página local. Se aparecer erro de coluna ausente, confira se o CSV tem exatamente data, categoria, canal, pedidos e receita.

Filtros úteis

Filtros devem responder perguntas reais. Em vez de colocar todos os campos disponíveis, comece com período, categoria e canal:

st.sidebar.header("Filtros")

data_min = df["data"].min().date()
data_max = df["data"].max().date()
periodo = st.sidebar.date_input("Período", value=(data_min, data_max))

categorias = st.sidebar.multiselect(
    "Categorias",
    options=sorted(df["categoria"].dropna().unique()),
    default=sorted(df["categoria"].dropna().unique()),
)

canais = st.sidebar.multiselect(
    "Canais",
    options=sorted(df["canal"].dropna().unique()),
    default=sorted(df["canal"].dropna().unique()),
)

inicio, fim = pd.to_datetime(periodo[0]), pd.to_datetime(periodo[1])
filtrado = df[
    (df["data"].between(inicio, fim))
    & (df["categoria"].isin(categorias))
    & (df["canal"].isin(canais))
]

Esse trecho já mostra uma habilidade importante para vagas de análise: transformar uma pergunta de negócio em recorte de dados. Em um projeto mais completo, você pode validar período vazio, formatar datas brasileiras e salvar filtros em parâmetros de URL.

Métricas principais

KPIs devem aparecer antes dos gráficos. Quem abre o painel quer saber rapidamente se o resultado melhorou, piorou ou precisa de investigação.

receita_total = filtrado["receita"].sum()
pedidos_total = int(filtrado["pedidos"].sum())
ticket_medio = receita_total / pedidos_total if pedidos_total else 0

col1, col2, col3 = st.columns(3)
col1.metric("Receita", f"R$ {receita_total:,.2f}".replace(",", "X").replace(".", ",").replace("X", "."))
col2.metric("Pedidos", f"{pedidos_total:,}".replace(",", "."))
col3.metric("Ticket médio", f"R$ {ticket_medio:,.2f}".replace(",", "X").replace(".", ",").replace("X", "."))

Em uma entrevista, explique que formatação monetária não é detalhe cosmético: um painel brasileiro precisa ser lido por pessoas brasileiras. Separador decimal, moeda e nomes de filtros devem estar em português.

Gráfico mensal

Agora agregue a receita por mês:

mensal = (
    filtrado.assign(mes=filtrado["data"].dt.to_period("M").astype(str))
    .groupby("mes", as_index=False)
    .agg(receita=("receita", "sum"), pedidos=("pedidos", "sum"))
)

grafico = px.bar(
    mensal,
    x="mes",
    y="receita",
    text="receita",
    title="Receita por mês",
)
grafico.update_layout(xaxis_title="Mês", yaxis_title="Receita")
st.plotly_chart(grafico, use_container_width=True)

Não exagere na quantidade de gráficos. Um dashboard com dez visualizações fracas costuma ser pior do que um painel com três visualizações que respondem perguntas claras: quanto vendemos, de onde veio a receita e quais categorias puxaram o resultado.

Tabela e exportação

Depois das métricas, ofereça a base filtrada para auditoria:

st.subheader("Dados filtrados")
st.dataframe(filtrado.sort_values("data", ascending=False), use_container_width=True)

csv_filtrado = filtrado.to_csv(index=False).encode("utf-8")
st.download_button(
    "Baixar CSV filtrado",
    data=csv_filtrado,
    file_name="vendas_filtradas.csv",
    mime="text/csv",
)

Esse botão simples transforma o painel em ferramenta de trabalho. A pessoa filtra o que precisa, confere os números e baixa o recorte para enviar, arquivar ou investigar.

Como transformar em portfólio

Para o projeto ficar forte, não publique apenas o código. Inclua no README:

  • qual problema o painel resolve;
  • quais colunas o CSV precisa ter;
  • como rodar localmente;
  • screenshots do dashboard;
  • principais decisões de limpeza e validação;
  • limitações conhecidas;
  • próximos passos, como autenticação, banco de dados ou deploy.

Também vale adicionar testes pequenos para funções de limpeza, mesmo que o Streamlit em si seja visual. Se a preparação dos dados ficar em uma função separada, você pode testar datas inválidas, receita vazia e colunas obrigatórias com pytest. Veja testes com pytest para organizar essa parte.

Próximos passos

Depois do primeiro dashboard, evolua com uma fonte realista: dados públicos, planilha exportada de um sistema fictício, API aberta ou banco SQLite. Se o volume crescer, leia sobre Python e PostgreSQL e ETL com Python. Para um caso corporativo, conecte o painel a uma rotina agendada que baixa dados, valida campos e gera logs.

O ponto principal é mostrar que você entende o ciclo completo: receber dados, limpar, calcular indicadores, apresentar visualmente e permitir que alguém tome uma decisão. Streamlit ajuda porque reduz o atrito da interface, mas o valor está na clareza do problema e na qualidade da análise.