Projetos
Pandas · Estoque · Desenvolvimento

Otimização de Estoque (ABC) — Como foi feito (explicado fácil)

Pensa numa papelaria com 33 mil produtos. Não dá pra contar todos toda semana. Mas se você descobre que ~26% dos itens respondem por 80% da venda — você conta esses 26% toda semana e o resto, de mês em mês. Esse é o princípio da curva ABC.

Nível Iniciante a intermediário Stack Python · Pandas Tipo Projeto analítico
Visão geral

O que é isso, em uma frase?

É a análise que pega 32.951 produtos do Olist (e-commerce brasileiro, Kaggle) e classifica em 3 grupos:

  • Classe A — produtos que acumulam até 80% da receita. Controle apertado: contagem semanal, estoque alto, reposição imediata.
  • Classe B — de 80% a 95% da receita. Controle moderado, contagem mensal.
  • Classe C — de 95% a 100%. Controle leve, contagem trimestral, cauda longa.

Por que importa? Porque atenção é um recurso finito. Tratar todos os produtos igual é desperdício. ABC é a forma matemática de dizer "esses aqui são os filhos prediletos" — não por simpatia, mas por receita.

Passo a passo

Da venda à classificação

1 · Pegar só o que importa. Junto order_items com orders, mantenho só pedidos com status delivered (devolução distorce a curva), e fico com product_id + price.

items  = pd.read_csv("olist_order_items_dataset.csv",
                     usecols=["order_id", "product_id", "price"])
orders = pd.read_csv("olist_orders_dataset.csv",
                     usecols=["order_id", "order_status"])
df = items.merge(orders, on="order_id", how="left")
df = df[df["order_status"] == "delivered"][["product_id", "price"]]

2 · Somar receita por SKU. Cada produto tem sua receita total. Ordeno do maior pro menor — é o passo que define a "ordem" da curva.

receita = (
    df.groupby("product_id")["price"]
      .sum()
      .sort_values(ascending=False)
      .reset_index(name="receita")
)

3 · Calcular o acumulado. O número-chave. cumsum() soma indo de cima pra baixo. Divido pelo total → tenho o % acumulado.

total = receita["receita"].sum()
receita["pct_acumulado"] = receita["receita"].cumsum() / total * 100
# product_id   receita   pct_acumulado
# p001         R$ 50k    2,1%
# p002         R$ 40k    3,8%
# p003         R$ 35k    5,3%  ... ate 100%

4 · Cortar nas linhas de 80% e 95%. pd.cut aplica bins (intervalos) numéricos e devolve a classe. Simples e elegante.

receita["classe"] = pd.cut(
    receita["pct_acumulado"],
    bins=[0, 80, 95, 100.01],
    labels=["A", "B", "C"],
)

5 · Resumir e ler com honestidade. Pareto literal diz "20% → 80%". O dataset disse 26% → 80%. Reportei 26%, não inflei pra 20%.

classe% SKUs% receita
A~26%80%
B~15%15%
C~59%5%

6 · Aplicação prática. A saída vai pro time de compras como uma planilha. Eles passam a tratar a classe A diferente: mais estoque de segurança, reposição automática, contagem cíclica semanal. A classe C continua existindo (cauda longa importa), mas sem perder noites de sono com ela.

Resultado

A curva ABC do Olist

O que dá pra levar daqui

Em uma linha: o que esse projeto ensina

Que nem todo SKU é igual, e a matemática (não a intuição) deve dizer quais merecem mais atenção. ABC é simples mas transformadora — toda gestão de estoque séria começa por ela.

Coisas técnicas que apareceram aqui: Pandas (groupby, sort_values, cumsum, cut), princípio de Pareto, binning categórico, filtro por status (pegadinha do delivered), leitura honesta dos números reais.