Logística & Entrega — Como foi feito (explicado fácil)
Pensa numa pizza prometida em 30min. Chega em 25 → você dá 5 estrelas. Chega em 1h → uma estrela e um xingo. Aqui medi quanto a nota do cliente cai por dia de atraso em 96 mil pedidos reais de e-commerce. O resultado é brutal: cai de 4,3 → 1,7.
O que é isso, em uma frase?
É uma análise sobre 96 mil pedidos do e-commerce Olist (Kaggle) que responde: "a nota do cliente cai quando a entrega atrasa? quanto?". A resposta, mensurada:
- Entrega no prazo → nota média ~4,3
- Atraso curto (1-7 dias) → nota média ~3,0
- Atraso muito longo (30+ dias) → nota média ~1,7
Por que importa? Porque em e-commerce com reputação por avaliação, isso é equivalente a perder cliente. Saber o número dá poder de decisão: vale pagar transportadora mais cara pra reduzir atraso? quanto custa cada dia de atraso em reputação?
Da data ao impacto
1 · Trazer as 2 datas-chave + a nota. Junto orders (que tem a data estimada e a data real de entrega) com reviews (que tem a nota de 1 a 5).
orders = pd.read_csv("olist_orders_dataset.csv",
usecols=["order_id", "order_status",
"order_estimated_delivery_date",
"order_delivered_customer_date"],
parse_dates=["order_estimated_delivery_date",
"order_delivered_customer_date"])
reviews = pd.read_csv("olist_order_reviews_dataset.csv",
usecols=["order_id", "review_score"])
df = orders.merge(reviews, on="order_id", how="inner")
2 · Filtrar com cuidado. Só pedidos delivered e com as duas datas preenchidas. Pedidos cancelados ou em rota não fazem parte da análise — métrica suja, conclusão suja.
df = df[df["order_status"] == "delivered"].dropna(
subset=["order_delivered_customer_date",
"order_estimated_delivery_date"]
)
3 · Calcular o atraso (em dias). Simples: data real menos data prometida. Negativo = adiantada, zero = no prazo, positivo = atraso. O .dt.days arranca só os dias inteiros.
df["dias_atraso"] = (
df["order_delivered_customer_date"]
- df["order_estimated_delivery_date"]
).dt.days
4 · Quebrar em faixas legíveis. "Dias contínuos" são bons pra cálculo, ruins pra leitura. Quebro em 5 faixas que falam a língua do negócio.
def faixa(d):
if d < -3: return "adiantada (3+ dias)"
if d <= 0: return "no prazo (-3 a 0)"
if d <= 7: return "atraso curto (1-7 dias)"
if d <= 30: return "atraso longo (8-30 dias)"
return "atraso muito longo (30+ dias)"
df["faixa"] = df["dias_atraso"].apply(faixa)
5 · Nota média por faixa. O cerne da análise — 3 linhas resolvem.
res = (df.groupby("faixa")["review_score"]
.agg(["mean", "count"])
.round(2))
print(res)
| faixa | nota média |
|---|---|
| Adiantada (3+ dias) | 4,3 |
| No prazo | 4,3 |
| Atraso curto (1-7d) | ~3,0 |
| Atraso longo (8-30d) | ~2,1 |
| Atraso muito longo (30+d) | 1,7 |
6 · Conclusão acionável. Atraso aceitável (até 7 dias) já tira mais de 1 estrela da média. Atraso longo cria detratores. Decisões que saem disso: revisar transportadora pra rotas críticas, comunicar proativamente quando o sistema previr atraso, considerar política de reembolso parcial pra recuperar nota.
Nota média × faixa de atraso
Em uma linha: o que esse projeto ensina
Que operação afeta marca. Logística não é problema só de logística — é problema de CX, marketing, retenção. Medir esse custo em número (não em "intuição de que afeta") é a base pra justificar investimento em transportadora melhor.
Coisas técnicas que apareceram aqui: Pandas (merge, dropna com subset, aritmética de datetime, .dt.days), classificação em faixas com apply, agregação por categoria com groupby, leitura crítica de filtros (status, datas válidas).