Planilhas
Do banco à planilha, passando pela análise.
Este é o caminho completo de um trabalho de dados: os dados moram no banco, a análise responde à pergunta, e a planilha é o que se manda para quem decide. As três peças conversam.
As quatro peças#
| Módulo | Para |
|---|---|
| `Arcane.Database` | SQLite: consultas, migrações, transações, modelos |
| `Arcane.Analytics` | média, desvio, correlação, regressão, describe |
| `Arcane.Excel` | ler e gravar .xlsx |
| `Arcane.IO` | arquivos, CSV, JSON |
Do banco à planilha#
adopt Arcane.Database as DB
adopt Arcane.Analytics as An
adopt Arcane.Excel as Xls
// 1. os dados
banco := DB.connect("vendas.db")
registros := DB.query(banco, "SELECT * FROM vendas ORDER BY qtd DESC")
// 2. a pergunta
tabela := An.from_records(registros)
descricao := An.describe(tabela)
correlacao := An.correlation(
[r["qtd"] cycle r in registros],
[r["preco"] cycle r in registros])
// 3. o entregável
livro := Xls.new()
aba := Xls.sheet(livro, "Vendas", registros)
Xls.set(aba, "E1", "receita")
cycle i from 2 to len(registros) + 1:
Xls.formula(aba, $"E{i}", $"C{i}*D{i}")
Xls.sheet(livro, "Estatísticas", [
["métrica", "valor"],
["vendas", len(registros)],
["correlação", round(correlacao, 3)]
])
Xls.save(livro, "relatorio.xlsx")`describe` sobre um frame#
Sobre uma lista, descreve a lista. Sobre um frame, descreve cada coluna:
An.describe(tabela)
// {
// "qtd": {count: 5, mean: 13.0, std: 9.6, min: 3, max: 27, …},
// "produto": {count: 0, type: "non-numeric"}
// }Colunas de texto aparecem marcadas em vez de zerarem o resultado inteiro. Booleanos são ignorados: em Python yes vale 1, e numa coluna de dados isso é ruído.
Escrever arquivos#
| Quer | Use |
|---|---|
| texto, JSON, CSV | IO.write_file, IO.write_json, IO.write_csv |
| planilha | Xls.save, Xls.quick |
| banco | DB.execute — e DB.close quando terminar |
| um caminho ao lado do programa | OS.beside("dados", "x.json") |
OS.beside resolve a partir do arquivo .df em execução, não de onde o usuário chamou o programa. Sem isso, rodar de duas pastas diferentes lê — ou não lê — arquivos diferentes.
Servir a planilha por HTTP#
route GET "/relatorio.xlsx":
livro := montar(consultar_agora())
Xls.save(livro, "/tmp/r.xlsx")
respond file "/tmp/r.xlsx"O arquivo não precisa existir antes do pedido. O projeto loja-web faz exatamente isso, com fórmulas que o Excel resolve ao abrir.
Uma armadilha de precedência#
// errado: divide o ZERO, não a soma
media := precos >> distill a, v: a + v 0 / len(precos)
// certo
soma := precos >> distill a, v: a + v 0
media := soma / len(precos)O valor inicial do distill vem depois do corpo. O relatório mostra a soma no lugar da média, e nada na tela denuncia — o número simplesmente está errado.