Pular para o conteúdo

Análise de dados

Carregar, descrever, agregar e projetar — o fluxo completo de uma análise.

Este é o código completo do exercício 176_analise_dados.df, que roda e verifica a si mesmo.

176_analise_dados.df
adopt Arcane.Analytics as An
adopt Arcane.Math as Math
adopt Arcane.Text as Text
adopt Arcane.Collections as Col

// ═══ DADOS ═══

record Venda:
    mes: Integer
    vendedor: String
    regiao: String
    valor: Number

bruto := [
    [1, "Ana", "sul", 12000], [1, "Bruno", "norte", 8500],
    [1, "Carla", "sul", 15000], [2, "Ana", "sul", 13500],
    [2, "Bruno", "norte", 9200], [2, "Carla", "sul", 11000],
    [3, "Ana", "sul", 16000], [3, "Bruno", "norte", 7800],
    [3, "Carla", "sul", 18500], [4, "Ana", "sul", 14200],
    [4, "Bruno", "norte", 11000], [4, "Carla", "sul", 19000]
]

vendas := bruto >> morph l: Venda(l[0], l[1], l[2], l[3])
valores := vendas >> morph v: v.valor

out Text.box("Analise de Vendas")

// ═══ ESTATISTICA DESCRITIVA ═══

out ""
out "── resumo ──"
out $"  registros:     {len(vendas)}"
out $"  total:         R$ {sum(valores)}"
out $"  media:         R$ {round(Math.mean(valores), 2)}"
out $"  mediana:       R$ {Math.median(valores)}"
out $"  desvio padrao: R$ {round(Math.stdev(valores), 2)}"
out $"  minimo:        R$ {min(valores)}"
out $"  maximo:        R$ {max(valores)}"

assert len(vendas) is 12, "doze registros"
assert sum(valores) is 155700, "total"

// ═══ QUARTIS E OUTLIERS ═══

q := An.quartiles(valores)
out ""
out "── distribuicao ──"
out $"  Q1: R$ {q["Q1"]}   Q2: R$ {q["Q2"]}   Q3: R$ {q["Q3"]}"
out $"  amplitude interquartil: R$ {An.iqr(valores)}"

outliers := An.outliers(valores)
out $"  outliers: {outliers}"

// ═══ AGREGACAO ═══

out ""
out "── por vendedor ──"
por_vendedor := Col.group_by(vendas, "vendedor")
resumos := []
cycle nome in sorted(por_vendedor.keys()):
    v := por_vendedor[nome] >> morph x: x.valor
    resumos.append({"nome": nome, "total": sum(v), "media": round(Math.mean(v), 2)})

cycle r in Col.sort_by_field(resumos, "total", yes):
    barra := "#".repeat(r["total"] * 30 ~/ max(sum(valores), 1))
    out $"  {r["nome"].pad_end(8)}R$ {str(r["total"]).pad_start(7)}  {barra}"

assert len(resumos) is 3, "tres vendedores"

out ""
out "── por regiao ──"
por_regiao := Col.group_by(vendas, "regiao")
cycle regiao in sorted(por_regiao.keys()):
    v := por_regiao[regiao] >> morph x: x.valor
    fatia := round(sum(v) * 100 / sum(valores), 1)
    out $"  {regiao.pad_end(8)}R$ {str(sum(v)).pad_start(7)}  ({fatia}%)"

// ═══ SERIE TEMPORAL ═══

out ""
out "── evolucao mensal ──"
por_mes := {}
cycle v in vendas:
    por_mes[v.mes] := por_mes.get(v.mes, 0) + v.valor

meses := sorted(por_mes.keys())
serie := meses >> morph m: por_mes[m]
maximo := max(serie)

cycle m in meses:
    total := por_mes[m]
    barra := "█".repeat(max(1, total * 30 ~/ maximo))
    out $"  mes {m}: {barra} R$ {total}"

assert len(meses) is 4, "quatro meses"

// ═══ TENDENCIA ═══

correlacao := An.correlation(meses, serie)
modelo := An.linear_regression(meses, serie)
previsao := An.predict_linear(modelo, 5)

out ""
out "── tendencia ──"
out $"  correlacao mes x total: {round(correlacao, 4)}"
out $"  reta: y = {round(modelo["slope"], 2)}x + {round(modelo["intercept"], 2)}"
out $"  ajuste (R2): {round(An.r_squared(meses, serie), 4)}"
out $"  previsao para o mes 5: R$ {round(previsao, 2)}"

assert correlacao bigger 0, "vendas crescendo"
assert previsao bigger serie[len(serie) - 1], "previsao acima do ultimo mes"

// ═══ MEDIA MOVEL ═══

out ""
out "── media movel (2 meses) ──"
movel := An.moving_average(serie, 2)
cycle i from 0 to len(movel) - 1:
    out $"  janela {i + 1}: R$ {round(movel[i], 2)}"

// ═══ CONCLUSAO ═══

melhor := Col.sort_by_field(resumos, "total", yes)[0]
crescimento := round((serie[len(serie) - 1] - serie[0]) * 100 / serie[0], 1)

out ""
out Text.box("Conclusao")
out $"  melhor vendedor: {melhor["nome"]} (R$ {melhor["total"]})"
out $"  crescimento no periodo: {crescimento}%"
out $"  ticket medio: R$ {round(Math.mean(valores), 2)}"

assert melhor["nome"] is "Carla", "Carla vendeu mais"
assert crescimento bigger 0, "houve crescimento"

As cinco etapas#

EtapaFaz
Modelarconverte listas anônimas em records tipados
Descrevermédia, mediana, desvio, quartis
Agregarpor vendedor, por região, por mês
Visualizarhistogramas em texto
Projetarcorrelação, regressão, previsão

Média e mediana contam histórias diferentes#

Quando as duas divergem muito, a distribuição é assimétrica — geralmente por causa de poucos valores muito altos ou baixos. Olhar as duas é mais informativo que olhar só a média.

Cuidado com extrapolação#

Prever o mês 5 a partir de 4 meses é razoável; prever o mês 50 não é. A reta descreve o passado observado, não garante o futuro.

As funções estão em Arcane.Analytics.