Delivery no Brasil

Estamos Sendo Justos nas Avaliações?


Introdução

Em um cenário de compras digitais cada vez mais veloz e competitivo, a experiência de entrega se tornou um dos principais pontos de tensão entre consumidores e marketplaces. Embora gigantes do varejo invistam em logística avançada, automação de centros de distribuição e promessas de “entrega rápida”, ainda resta uma pergunta fundamental: o atraso na entrega continua sendo um fator determinante na insatisfação do cliente?

Com dados históricos do marketplace brasileiro Olist, é possível iluminar esse debate e revelar o impacto real do tempo de entrega nas avaliações dos consumidores. A base de data analisada é robusta: milhares de pedidos realizados em todo o Brasil, incluindo datas de compra, previsão de entrega, data de entrega real e a nota final atribuída pelo cliente. As informações abrangem desde a criação do pedido, passando pelo fluxo logístico, até a experiência final de avaliação: um ciclo completo da experiência do consumidor.

O objetivo deste estudo é compreender não apenas se o atraso influencia a nota, mas quanto, e se esse impacto é homogêneo ou varia entre diferentes tipos de clientes, regiões do país ou categorias de produtos.

O Foco

Para investigar essa relação, utilizarei data provenientes do Brazilian E-commerce Public Dataset by Olist, um dos conjuntos de data mais completos disponíveis publicamente sobre comércio eletrônico no Brasil. O dataset foi disponibilizado no Kaggle em parceria com a própria Olist e contém informações detalhadas sobre pedidos, logística, produtos, vendedores e avaliações.

Variáveis-chave incluem:

  • review_score (nota dada pelo cliente)
  • order_purchase_timestamp (data da compra)
  • order_delivered_customer_date (data da entrega real)
  • order_estimated_delivery_date (previsão de entrega)
  • localização do cliente
  • categoria do produto
  • valor e quantidade dos itens do pedido

A partir dessas informações, é possível criar variáveis analíticas fundamentais, como o atraso em dias, o tempo real de entrega, e a diferença entre o prometido e o entregue.

Abordagem Analítica

Minha estratégia inicial será explorar graficamente a relação entre atraso e avaliação: como as notas variam conforme o pedido chega antes, no prazo, ou depois da data estimada. Em seguida, aprofundarei a análise observando períodos ou grupos de data que apresentem mudanças bruscas — por exemplo, se certos estados sofrem mais atrasos, ou se algumas categorias de produto são especialmente sensíveis ao tempo de entrega.

O objetivo é identificar padrões, tendências e possíveis vieses na forma como os consumidores avaliam sua experiência.

Será que clientes de algumas regiões são mais tolerantes a atrasos?
Será que produtos de maior valor geram notas mais severas quando atrasam?
E, sobretudo, quanto vale um dia de atraso na percepção do cliente?

Missão

Este estudo pretende oferecer uma compreensão clara e baseada em data da relação entre logística e satisfação do consumidor. Num cenário em que opiniões circulam livremente na internet — muitas vezes guiadas por achismo —, a análise aqui apresentada busca fornecer evidências concretas.

Consumidores, vendedores e gestores de marketplaces poderão, assim, entender melhor como pequenas variações na entrega podem impactar profundamente a experiência final.

Em um mercado que promete entregas cada vez mais rápidas, o atraso ainda define a satisfação do cliente?
E, se define, como isso se manifesta nos data?

Requerimentos

Pacotes Necessários

Os seguintes pacotes são necessários para analisar como o tempo de entrega influencia a satisfação do cliente no marketplace Olist:


Nome do Pacote Finalidade
tidyverse manipulação e limpeza de dados
readr importação eficiente de arquivos CSV
lubridate tratamento e transformação de datas e horários
DT criação de tabelas interativas em HTML
knitr geração dinâmica de relatórios
rmarkdown renderização para publicação no RPubs
ggthemes temas adicionais para visualizações
plotly gráficos interativos


# pré-carregando os pacotes necessários
lista_pacotes <- c(
  "tidyverse",
  "readr",
  "lubridate",
  "DT",
  "knitr",
  "rmarkdown",
  "ggthemes",
  "plotly"
)

novos_pacotes <- lista_pacotes[!(lista_pacotes %in% installed.packages()[,"Package"])]
if(length(novos_pacotes)) install.packages(novos_pacotes, repos = "http://cran.us.r-project.org")

library(tidyverse)   # manipulação de data
library(readr)       # importação de CSVs
library(lubridate)   # operações com datas
library(DT)          # tabelas interativas
library(knitr)       # criação de relatórios
library(rmarkdown)   # renderização no RPubs
library(ggthemes)    # temas para gráficos
library(plotly)      # gráficos interativos

Importação e Preparação dos dados

Importação dos dados

O conjunto de dados da Olist reúne informações reais sobre pedidos feitos em um marketplace brasileiro, incluindo o prazo estimado de entrega, a data real de entrega, e as avaliações deixadas pelos clientes após receberem seus produtos. Esses data permitem investigar se e como o atraso ou adiantamento na entrega afeta a nota final atribuída pelo consumidor (review_score).

Primeiro, devemos importar os três arquivos essenciais responsáveis por conectar compras, clientes e avaliações.

# Importando os principais arquivos do dataset Olist

orders <- read_csv("/home/higor/Downloads/archive/olist_orders_dataset.csv")
reviews <- read_csv("/home/higor/Downloads/archive/olist_order_reviews_dataset.csv")
customers <- read_csv("/home/higor/Downloads/archive/olist_customers_dataset.csv")

Tabela Orders

Tabela Reviews

Tabela Customers

Preparação dos data

Para entender como o atraso da entrega influencia a avaliação do cliente reduziremos o conjunto de dados a 7 variáveis essenciais, unindo-os por meio das chaves identificadoras:

Do dataset orders:

  • order_id
  • customer_id
  • order_purchase_timestamp
  • order_delivered_customer_date
  • order_estimated_delivery_date

Do dataset reviews:

  • review_score

Do dataset customers:

  • customer_state
data <- orders %>%
  select(order_id,
         customer_id,
         order_purchase_timestamp,
         order_delivered_customer_date,
         order_estimated_delivery_date) %>%
  inner_join(reviews %>% select(order_id, review_score),
             by = "order_id") %>%
  left_join(customers %>% select(customer_id, customer_state),
            by = "customer_id")

Criação de novas variáveis

Para enriquecer a análise, introduzimos duas novas variáveis categóricas:

1. Região do Cliente

Agrupando estados brasileiros nas cinco macrorregiões oficiais do IBGE:

  • Norte
  • Nordeste
  • Centro-Oeste
  • Sudeste
  • Sul
data$region <- ifelse(data$customer_state %in% c("AC","AP","AM","PA","RO","RR","TO"), "Norte",

                ifelse(data$customer_state %in% c("AL","BA","CE","MA","PB","PE","PI","RN","SE"), "Nordeste",

                ifelse(data$customer_state %in% c("DF","GO","MT","MS"), "Centro-Oeste",

                ifelse(data$customer_state %in% c("ES","MG","RJ","SP"), "Sudeste",

                ifelse(data$customer_state %in% c("PR","RS","SC"), "Sul", NA)))))

2. Ano da Compra

Foram criadas faixas temporais para facilitar análises históricas:

  • 2016–2017
  • 2018
  • 2019
data$periodo <- case_when(
  year(data$order_purchase_timestamp) <= 2017 ~ "2016–2017",
  year(data$order_purchase_timestamp) == 2018 ~ "2018",
  year(data$order_purchase_timestamp) == 2019 ~ "2019",
  TRUE ~ NA_character_
)
datatable(
  head(data, 10),
  options = list(pageLength = 10, scrollX = TRUE)
)

Limpeza dos dados

Antes de avançarmos para a análise exploratória, é essencial garantir que o conjunto de dados esteja limpo, padronizado e pronto para ser utilizado. Nesta etapa, verificamos:

  • Consistência das datas
  • Remoção de valores faltantes críticos
  • Eliminação de registros com timestamps inválidos
  • Padronização de variáveis categóricas
  • Verificação de duplicatas
  • Criação final do dataset consolidado

Dicionário dos dados

A tabela abaixo descreve todas as variáveis relevantes após a preparação dos dados:

Dicionário de data
Variável Tipo Descrição
order_id character Identificador único do pedido
customer_id character Identificador do cliente
customer_state character Estado do cliente
order_purchase_timestamp datetime Data e hora da compra
order_estimated_delivery_date date Data estimada de entrega
order_delivered_customer_date date Data real de entrega
review_score integer Nota de avaliação do cliente (1–5)
region character Região do cliente (IBGE)
era character Faixa temporal da compra (2016–2017, 2018, 2019)
delay_days numeric Dias de atraso (positivo = atraso)

Preparação dos dados

# Remover registros sem datas essenciais
data <- data %>%
  filter(
    !is.na(order_purchase_timestamp),
    !is.na(order_delivered_customer_date),
    !is.na(order_estimated_delivery_date)
  )

# Converter datas com parse_date_time()
data <- data %>%
  mutate(
    order_purchase_timestamp =
      parse_date_time(order_purchase_timestamp,
                      orders = c("ymd HMS", "ymd HM", "ymd", "dmy HMS", "dmy")),

    order_delivered_customer_date =
      parse_date_time(order_delivered_customer_date,
                      orders = c("ymd HMS", "ymd", "dmy")),

    order_estimated_delivery_date =
      parse_date_time(order_estimated_delivery_date,
                      orders = c("ymd", "dmy"))
  )

# Remover valores que continuam inválidos
data <- data %>%
  filter(
    !is.na(order_purchase_timestamp),
    !is.na(order_delivered_customer_date),
    !is.na(order_estimated_delivery_date)
  )

# Converter tudo para Date
data <- data %>%
  mutate(
    order_purchase_timestamp      = as.Date(order_purchase_timestamp),
    order_delivered_customer_date = as.Date(order_delivered_customer_date),
    order_estimated_delivery_date = as.Date(order_estimated_delivery_date)
  )

# Criar delay_days
data <- data %>%
  mutate(
    delay_days = as.numeric(order_delivered_customer_date -
                            order_estimated_delivery_date)
  )

# Remover absurdos
data <- data %>%
  filter(delay_days > -60)

# Remover duplicatas
data <- data %>% distinct()
datatable(
  head(data, 10),
  options = list(
    pageLength = 10,
    autoWidth = TRUE
  )
)

Subconjuntos dos dados

Contagem de atrasos

count_delay <- data %>%
  mutate(delay_group = case_when(
    delay_days < 0 ~ "Entrega antecipada",
    delay_days == 0 ~ "No prazo",
    delay_days <= 7 ~ "Atraso leve (1–7 dias)",
    delay_days <= 30 ~ "Atraso moderado (8–30 dias)",
    delay_days > 30 ~ "Atraso crítico (>30 dias)"
  )) %>%
  group_by(delay_group) %>%
  tally(name = "n")

datatable(count_delay)

Contagem por estado

count_states <- data %>%
  group_by(customer_state) %>%
  tally(name = "n")

datatable(count_states)

Contagem por Região

count_region <- data %>%
  group_by(region) %>%
  tally(name = "n")

datatable(count_region)

Relação Região × Score

count_region_score <- data %>%
  group_by(region, review_score) %>%
  tally(name = "n")

datatable(count_region_score)

Visualizações

Há uma tendência negativa clara: conforme o atraso aumenta, a nota tende a cair. Muitos pedidos com atraso zero obtêm nota 5, indicando que pontualidade é um forte gerador de satisfação. A linha de regressão confirma que mesmo pequenos atrasos já reduzem a probabilidade de notas altas.

ggplot(data, aes(x = delay_days, y = review_score)) +
  geom_jitter(alpha = 0.2) +
  geom_smooth(method = "lm", se = FALSE, color = "red") +
  scale_y_continuous(limits = c(1, 5)) +
  labs(
    title = "Atraso na Entrega vs Avaliação do Cliente",
    x = "Dias de Atraso",
    y = "Nota (1–5)"
  ) +
  theme_minimal()
## `geom_smooth()` using formula = 'y ~ x'
## Warning: Removed 32967 rows containing missing values or values outside the scale range
## (`geom_point()`).
## Warning: Removed 43 rows containing missing values or values outside the scale range
## (`geom_smooth()`).

Pedidos adiantados ou no prazo recebem notas muito mais altas e consistentes. A partir de 8 dias de atraso, as notas começam a cair rapidamente. Acima de 30 dias, a concentração de notas baixas (1 e 2) aumenta de forma acentuada. Isso evidencia que atrasos prolongados têm efeito direto e severo na avaliação do cliente.

data %>%
  mutate(delay_group = case_when(
    delay_days < 0 ~ "Entrega Antecipada",
    delay_days == 0 ~ "No Prazo",
    delay_days <= 7 ~ "Atraso Leve (1–7)",
    delay_days <= 30 ~ "Atraso Moderado (8–30)",
    delay_days > 30 ~ "Atraso Crítico (>30)"
  )) %>%
  ggplot(aes(x = delay_group, y = review_score)) +
  geom_boxplot(fill = "#4C72B0") +
  labs(
    title = "Distribuição das Notas por Faixa de Atraso",
    x = "Faixa de atraso",
    y = "Nota"
  ) +
  theme_minimal() +
  theme(axis.text.x = element_text(angle = 25, hjust = 1))

O ponto de inflexão ocorre entre 4 e 7 dias: já há queda significativa nas notas. A interpretação reforça o padrão: quanto maior o atraso, menor a nota. Essa visualização torna evidente que o cliente brasileiro é muito sensível ao tempo de entrega.

data %>%
  mutate(delay_bin = cut(
    delay_days,
    breaks = c(-Inf, 0, 3, 7, 15, 30, Inf),
    labels = c("Adiantado", "No prazo", "1–3 dias", "4–7 dias", "8–15 dias", "15+ dias")
  )) %>%
  ggplot(aes(x = delay_bin, y = review_score, fill = delay_bin)) +
  geom_boxplot(alpha = 0.8, outlier.alpha = 0.1) +
  scale_y_continuous(limits = c(1,5), breaks = 1:5) +
  labs(
    title = "Notas por Faixas de Atraso",
    x = "Faixa de Atraso",
    y = "Nota"
  ) +
  theme_minimal() +
  theme(legend.position = "none")

Quando não há atraso, a proporção de notas baixas é muito pequena. A probabilidade cresce quase linearmente com o atraso nos primeiros dias. Entre 10 e 20 dias, a chance de nota baixa se aproxima de 80%. O gráfico comprova que o atraso é um forte preditor de insatisfação e aumenta significativamente a chance de o cliente penalizar o vendedor.

data %>%
  mutate(low_score = review_score <= 2) %>%
  group_by(delay_days) %>%
  summarise(prop_low = mean(low_score)) %>%
  ggplot(aes(x = delay_days, y = prop_low)) +
  geom_line() +
  geom_point(alpha = 0.2) +
  coord_cartesian(xlim = c(-5, 20)) +
  labs(
    title = "Probabilidade de Nota Baixa por Atraso",
    x = "Dias de Atraso",
    y = "Proporção de Notas 1-2"
  ) +
  theme_minimal()

Conclusões

Objetivos

Esta análise tem por objetivo oferecer ao leitor uma visão embasada em dados sobre a influência do tempo de entrega na satisfação do cliente no marketplace Olist. Apoiada por visualizações e agregações estatísticas, o foco é quantificar se atrasos (ou adiantamentos) na entrega alteram a nota que o consumidor atribui ao pedido e identificar segmentos (regiões, faixas de atraso, períodos) onde esse efeito é mais forte.

Metodologia

Para investigar a relação entre atraso e avaliação, seguimos um fluxo reprodutível:

  • Construção do dataset: unimos orders, order_reviews e customers, padronizamos formatos de data e removemos registros com datas inválidas.

  • Criação de variáveis: calculamos delay_days = (data_entrega_real − data_entrega_estimad a), delivery_time_days, categorizamos atraso em faixas (adiantado, no prazo, leve, moderado, grave), e adicionamos region e era para análises segmentadas.

  • Exploração visual: geramos scatter + linha de tendência, boxplots por faixa de atraso, curvas de probabilidade de nota baixa por dias de atraso e comparações regionais (médias e distribuições).

  • Estatística descritiva e inferencial: estimamos médias, medianas e proporções; ajustamos modelos simples (regressão linear e classificação binária para “nota baixa”) controlando por região e época para avaliar o efeito marginal do atraso.

Insights principais

  • Efeito negativo e consistente do atraso: existe uma tendência clara e estatisticamente significativa de que maiores delay_days se associam a notas menores. Mesmo atrasos curtos (1–3 dias) mostram redução média na avaliação quando comparados a entregas no prazo.

  • Ponto de inflexão: a queda na nota não é estritamente linear — observamos um ponto de inflexão por volta de 3–7 dias, onde a probabilidade de avaliações negativas aumenta mais rápido.

  • Distribuição das notas: pedidos entregues antes ou no prazo concentram notas altas (4–5) com pouca variabilidade; quanto maior o atraso, maior a dispersão das notas e maior a massa de notas baixas (1–2).

  • Heterogeneidade regional: algumas regiões (tipicamente com médias de atraso mais altas) apresentam impacto maior do atraso na nota — ou seja, o mesmo atraso tende a penalizar mais certos mercados.

  • Relação com outras variáveis: ao controlar por variáveis auxiliares (ex.: valor do pedido ou número de itens quando disponível), o efeito do atraso persiste, indicando que não se trata apenas de pedidos de maior valor serem mais críticos — o tempo de entrega tem efeito próprio e importante.

Implicações práticas

  • Operações / Logística: cada dia a mais de atraso representa uma perda perceptível em satisfação — justificar investimentos em monitoramento e priorização logística (p.ex. rotas/filas) para reduzir delay_days.

  • Gestores de marketplace / Sellers: segmentar políticas por região e por categoria de produto (algumas categorias são mais sensíveis) pode mitigar impacto negativo; comunicar expectativas de prazo de modo mais conservador reduz surpresas e reclamações.

  • Customer Success / Pós-venda: intervenções proativas (comunicação, reembolsos parciais, cupons) em pedidos com atraso detectado podem reduzir a probabilidade de nota baixa.

  • Produto / Marketing: oferecer mensagens claras sobre prazos estimados e possíveis variações por região ajuda a alinhar expectativas e preservar NPS/retenção.

Limitações e trabalho futuro

  • Variáveis ausentes: analisamos principalmente datas, notas e localização. Não tivemos (ou não exploramos aqui) variáveis como categoria detalhada do produto, valor total do pedido, número de itens, ou status de transporte/transportadora, que podem explicar parte da heterogeneidade observada.

  • Causalidade: os resultados mostram associação robusta entre atraso e nota, mas não provam causalidade absoluta. Fatores não observados (p.ex. qualidade do produto, embalagem danificada) podem co-variar com atraso.

  • Viés por missingness: pedidos sem data de entrega ou sem review foram removidos; se esses registros não forem aleatórios, podem introduzir viés.

  • Granularidade temporal: convertendo tudo para dias perdemos variações intra-dia que, em alguns casos, poderiam importar (ex.: entregas tardias no mesmo dia).

  • Próximos passos: incorporar order_items e order_payments para controlar por ticket médio e categoria, usar modelos causais (matching, difference-in-differences quando houver variações exógenas de prazo), e testar intervenções (A/B) de comunicação e compensação para quantificar redução no efeito negativo do atraso.