Uma análise completa de vendas

Importar, validar, relacionar e agregar dados, conservando decisões e verificações.

Perguntar sobre esta página

ChatGPTClaudePerplexityGeminiCopiar e abrir

Brain rot

A seguirPara ti

@resumos.feup

som original ·

Definições

Leitura

Mudar de trecho
Legendas
Mostrar no vídeo
Vídeos de fundo

O texto, o áudio e os teus vídeos ficam neste dispositivo.

Créditos dos vídeos e da voz

Partilhar página

Vamos responder a duas perguntas: quanto faturou cada cidade e qual foi o preço médio por unidade vendida? Temos um CSV com vendas e outra tabela com preços por produto. Os dados abaixo são fictícios e pequenos para poderes verificar cada passo.

Definir as observações

Cada linha de vendas identifica uma venda, com código único, cidade, produto e quantidade. O catálogo tem um preço por produto. Quantidade deve ser positiva e o preço deve ser conhecido antes de calcular a faturação.

VendaCidadeProdutoQuantidade
1PortoA2
2PortoB3
3BragaA5
4BragaC4

A custa 1,50 euros, B custa 1,20 e C custa 2,00. À mão, Porto fatura 6,60 e Braga 15,50. O total é 22,10 euros e há 14 unidades.

Código do princípio ao fim

Análise reproduzível
from io import StringIO
import pandas as pd

csv_vendas = 'venda;cidade;produto;quantidade\n1;Porto;A;2\n2;Porto;B;3\n3;Braga;A;5\n4;Braga;C;4\n'
vendas = pd.read_csv(StringIO(csv_vendas), sep=";", dtype={"produto": "string"})
precos = pd.DataFrame({"produto": ["A", "B", "C"], "preco": [1.5, 1.2, 2.0]})

assert vendas["venda"].is_unique
assert vendas[["cidade", "produto", "quantidade"]].notna().all().all()
assert (vendas["quantidade"] > 0).all()
assert precos["produto"].is_unique

dados = vendas.merge(precos, on="produto", how="left", validate="many_to_one")
assert len(dados) == len(vendas)
assert dados["preco"].notna().all()
dados["total"] = dados["quantidade"] * dados["preco"]

relatorio = dados.groupby("cidade", as_index=False).agg(
    unidades=("quantidade", "sum"),
    faturacao=("total", "sum"),
    vendas=("venda", "size"),
)
relatorio["preco_medio"] = relatorio["faturacao"] / relatorio["unidades"]
assert abs(relatorio["faturacao"].sum() - dados["total"].sum()) < 1e-10
print(relatorio.round(4).to_string(index=False))
print("Faturação total:", round(dados["total"].sum(), 2))
print("Unidades:", dados["quantidade"].sum())
print("Preço médio global:", round(dados["total"].sum() / dados["quantidade"].sum(), 4))
Dados de entrada

O preço médio por unidade é 1,32 euros no Porto e aproximadamente 1,7222 em Braga. O global é 22,10 / 14, aproximadamente 1,5786 euros. Não calculamos a média das médias das cidades, porque venderam quantidades diferentes.

Por que cada verificação existe

A chave de venda única impede contar o mesmo identificador duas vezes. As colunas essenciais não podem estar ausentes. A quantidade positiva faz parte do contrato deste exemplo; noutro conjunto, quantidades negativas podem representar devoluções e precisam de outra regra.

A chave de produto única evita multiplicar linhas na junção. how="left" conserva as vendas, permitindo detetar produtos sem preço. Só calculamos totais depois de confirmar que todos têm correspondência.

A contagem de linhas deve manter-se na junção muitos-para-um. A soma da faturação dos grupos deve coincidir com a soma antes de agrupar. Estas verificações não provam que os preços reais estão corretos, mas detetam perdas e duplicações no processamento.

Acrescentar uma situação incompleta

Substitui C por D numa das vendas e volta a executar. A verificação dos preços falha antes de produzir o relatório. Para continuar, é preciso consultar o catálogo ou definir uma política para vendas sem preço. Não substituas o preço em falta por zero só para obter uma tabela final.

Duplica a linha de A no catálogo e executa novamente. validate="many_to_one" rejeita a junção. Sem essa verificação, as vendas de A seriam duplicadas e a soma ficaria errada.

Preparar uma resolução de avaliação

Lê o pedido e identifica a unidade de análise. Escreve a chave que identifica cada linha, as colunas de que precisas e o resultado esperado. Depois escolhe seleção, transformação, junção ou agregação conforme a pergunta.

Antes de executar, prevê pelo menos uma célula e o número de linhas do resultado. Depois de executar, confere esse caso e um total que deva conservar-se. Na resposta, inclui o código, o valor obtido e a sua interpretação com unidade. Uma tabela correta sem explicar o que cada linha representa pode não responder à pergunta.

Exercícios

Calcular o preço médio global

Porto faturou 6,60 euros em 5 unidades e Braga 15,50 em 9. Qual é o preço médio global por unidade? Arredonda a quatro casas decimais.

Primeira pista

A média global usa as somas da faturação e das unidades.

Mais uma pista
Divide 22,10 por 14.
Ver solução

O resultado é aproximadamente 1,5786 euros por unidade. Uma média simples das duas médias daria igual peso a cidades com quantidades diferentes.

Erros frequentes

Somar médias ou calcular a sua média simples sem ponderar as unidades.

Voltar à explicação
Detetar um catálogo duplicado

O catálogo passa a ter duas linhas para o mesmo produto. Explica o efeito numa junção e como a análise o deteta antes do relatório.

Primeira pista

Uma junção cria um par para cada correspondência da chave.

Mais uma pista
O catálogo deve ter uma única linha por produto.
Ver solução

A junção duplicaria as vendas desse produto e poderia aumentar a faturação. A unicidade da chave e validate=“many_to_one” impedem continuar com esse catálogo. Não elimines arbitrariamente um preço sem resolver a ambiguidade.

Confere a tua resposta:

  • Expliquei que cada venda desse produto encontra duas correspondências.
  • Identifiquei validate="many_to_one" como verificação da relação.
  • Indiquei que conferir linhas e totais ajuda a detetar multiplicação.

Erros frequentes

Aceitar o relatório porque o código executou ou escolher o primeiro preço sem uma regra.

Voltar à explicação

À tua maneira

Aparência

Modo de cor
Tema
Cor de destaque

Leitura

Fonte de leitura

Álgebra, lógica e uma ideia de cada vez.

Código

Fonte do código

CSS personalizado

Ativa uma sugestão ou guarda o teu CSS. Só muda este navegador.

Usa --page, --text e --accent para acompanhar o tema.

Seletores e recuperação

.site-header, .prose, .course-card, [data-reading-history], [data-playground] e .page-actions.

Abre a aparência com a tecla vírgula ou no rodapé. Se o CSS esconder os controlos, abre esta página sem CSS personalizado.

Pesquisar

Escreve para pesquisar em todo o site.

para escolher · Enter para abrir · Esc para fechar

Atalhos de teclado

Clica numa tecla para a mudar. Esc cancela. Backspace desativa.

PesquisarCtrl / Cmd K

Os atalhos não interferem enquanto escreves. Tab e Enter funcionam sempre.