library(tidyverse)
library(readr)
library(gt)
library(summarytools)
library(ggplot2)
library(corrplot)
library(patchwork)Estatística para Cientistas de Dados 26.1
1 Carregando os pacotes
1.1 Descrição dos pacotes
tidyverse para manipulação e transformação de base de dados
readr para carregar as bases de dados
gt para melhorar a visualização de tabelas
summarytools para gerar descrição estatística das variáveis
ggplot2 para gerar gráficos
corrplot para fazer a matriz de correlação entre variáveis
patchwork para combinar gráficos dentro de uma função
2 Carregando os dados
reviews = read_csv("olist_order_reviews_dataset.csv")
pedidos = read_csv("olist_orders_dataset.csv")
pagamentos = read_csv("olist_order_payments_dataset.csv")
itens = read_csv("olist_order_items_dataset.csv")2.1 Descrição das bases de dados
A base olist_order_reviews_dataset contém as avaliações feitas pelos clientes após a entrega dos pedidos. Cada registro corresponde a uma avaliação associada a um pedido específico. A base inclui informações como a nota atribuída pelo cliente (de 1 a 5), o identificador da avaliação, o identificador do pedido e timestamps relacionados ao envio e à criação da avaliação. Esses dados permitem analisar o nível de satisfação dos clientes e investigar possíveis fatores associados a avaliações negativas.
head(reviews) |>
gt()| review_id | order_id | review_score | review_comment_title | review_comment_message | review_creation_date | review_answer_timestamp |
|---|---|---|---|---|---|---|
| 7bc2406110b926393aa56f80a40eba40 | 73fc7af87114b39712e6da79b0a377eb | 4 | NA | NA | 2018-01-18 | 2018-01-18 21:46:59 |
| 80e641a11e56f04c1ad469d5645fdfde | a548910a1c6147796b98fdf73dbeba33 | 5 | NA | NA | 2018-03-10 | 2018-03-11 03:05:13 |
| 228ce5500dc1d8e020d8d1322874b6f0 | f9e4b658b201a9f2ecdecbb34bed034b | 5 | NA | NA | 2018-02-17 | 2018-02-18 14:36:24 |
| e64fb393e7b32834bb789ff8bb30750e | 658677c97b385a9be170737859d3511b | 5 | NA | Recebi bem antes do prazo estipulado. | 2017-04-21 | 2017-04-21 22:02:06 |
| f7c4243c7fe1938f181bec41a392bdeb | 8e6bfb81e283fa7e4f11123a3fb894f1 | 5 | NA | Parabéns lojas lannister adorei comprar pela Internet seguro e prático Parabéns a todos feliz Páscoa | 2018-03-01 | 2018-03-02 10:26:53 |
| 15197aa66ff4d0650b5434f1b46cda19 | b18dcdf73be66366873cd26c5724d1dc | 1 | NA | NA | 2018-04-13 | 2018-04-16 00:39:37 |
A base olist_orders_dataset reúne informações gerais sobre os pedidos realizados na plataforma. Cada registro corresponde a um pedido único e inclui dados como o identificador do pedido, o identificador do cliente e diversas datas associadas ao processo logístico, incluindo aprovação do pedido, envio ao transportador, entrega ao cliente e prazo estimado de entrega. Essa base é fundamental para analisar o desempenho logístico e calcular métricas como tempo de entrega e ocorrência de atrasos.
head(pedidos) |>
gt()| order_id | customer_id | order_status | order_purchase_timestamp | order_approved_at | order_delivered_carrier_date | order_delivered_customer_date | order_estimated_delivery_date |
|---|---|---|---|---|---|---|---|
| e481f51cbdc54678b7cc49136f2d6af7 | 9ef432eb6251297304e76186b10a928d | delivered | 2017-10-02 10:56:33 | 2017-10-02 11:07:15 | 2017-10-04 19:55:00 | 2017-10-10 21:25:13 | 2017-10-18 |
| 53cdb2fc8bc7dce0b6741e2150273451 | b0830fb4747a6c6d20dea0b8c802d7ef | delivered | 2018-07-24 20:41:37 | 2018-07-26 03:24:27 | 2018-07-26 14:31:00 | 2018-08-07 15:27:45 | 2018-08-13 |
| 47770eb9100c2d0c44946d9cf07ec65d | 41ce2a54c0b03bf3443c3d931a367089 | delivered | 2018-08-08 08:38:49 | 2018-08-08 08:55:23 | 2018-08-08 13:50:00 | 2018-08-17 18:06:29 | 2018-09-04 |
| 949d5b44dbf5de918fe9c16f97b45f8a | f88197465ea7920adcdbec7375364d82 | delivered | 2017-11-18 19:28:06 | 2017-11-18 19:45:59 | 2017-11-22 13:39:59 | 2017-12-02 00:28:42 | 2017-12-15 |
| ad21c59c0840e6cb83a9ceb5573f8159 | 8ab97904e6daea8866dbdbc4fb7aad2c | delivered | 2018-02-13 21:18:39 | 2018-02-13 22:20:29 | 2018-02-14 19:46:34 | 2018-02-16 18:17:02 | 2018-02-26 |
| a4591c265e18cb1dcee52889e2d8acc3 | 503740e9ca751ccdda7ba28e9ab8f608 | delivered | 2017-07-09 21:57:05 | 2017-07-09 22:10:13 | 2017-07-11 14:58:04 | 2017-07-26 10:57:55 | 2017-08-01 |
A base olist_order_payments_dataset contém informações sobre os pagamentos realizados para cada pedido. Um mesmo pedido pode possuir mais de um registro nesta base, representando diferentes parcelas ou formas de pagamento utilizadas pelo cliente. As variáveis incluem o tipo de pagamento, o número de parcelas e o valor pago. Esses dados permitem analisar padrões financeiros das transações e a relação entre valores pagos e satisfação do cliente.
head(pagamentos) |>
gt()| order_id | payment_sequential | payment_type | payment_installments | payment_value |
|---|---|---|---|---|
| b81ef226f3fe1789b1e8b2acac839d17 | 1 | credit_card | 8 | 99.33 |
| a9810da82917af2d9aefd1278f1dcfa0 | 1 | credit_card | 1 | 24.39 |
| 25e8ea4e93396b6fa0d3dd708e76c1bd | 1 | credit_card | 1 | 65.71 |
| ba78997921bbcdc1373bb41e913ab953 | 1 | credit_card | 8 | 107.78 |
| 42fdf880ba16b47b59251dd489d4441a | 1 | credit_card | 2 | 128.45 |
| 298fcdf1f73eb413e4d26d01b25bc1cd | 1 | credit_card | 2 | 96.12 |
A base olist_order_items_dataset descreve os produtos incluídos em cada pedido. Como um pedido pode conter múltiplos produtos, cada linha representa um item específico dentro de um pedido. A base inclui informações como identificador do produto, vendedor, preço do item e valor do frete associado. Esses dados permitem analisar o valor total dos pedidos e características dos produtos vendidos.
head(itens) |>
gt()| order_id | order_item_id | product_id | seller_id | shipping_limit_date | price | freight_value |
|---|---|---|---|---|---|---|
| 00010242fe8c5a6d1ba2dd792cb16214 | 1 | 4244733e06e7ecb4970a6e2683c13e61 | 48436dade18ac8b2bce089ec2a041202 | 2017-09-19 09:45:35 | 58.90 | 13.29 |
| 00018f77f2f0320c557190d7a144bdd3 | 1 | e5f2d52b802189ee658865ca93d83a8f | dd7ddc04e1b6c2c614352b383efe2d36 | 2017-05-03 11:05:13 | 239.90 | 19.93 |
| 000229ec398224ef6ca0657da4fc703e | 1 | c777355d18b72b67abbeef9df44fd0fd | 5b51032eddd242adc84c38acab88f23d | 2018-01-18 14:48:30 | 199.00 | 17.87 |
| 00024acbcdf0a6daa1e931b038114c75 | 1 | 7634da152a4610f1595efa32f14722fc | 9d7a1d34a5052409006425275ba1c2b4 | 2018-08-15 10:10:18 | 12.99 | 12.79 |
| 00042b26cf59d7ce69dfabb4e55b4fd9 | 1 | ac6c3623068f30de03045865e4e10089 | df560393f3a51e74553ab94004ba5c87 | 2017-02-13 13:57:51 | 199.90 | 18.14 |
| 00048cc3ae777c65dbb7d2a0634bc1ea | 1 | ef92defde845ab8450f9d70c526ef70f | 6426d21aca402a131fc0a5d0960a3c90 | 2017-05-23 03:55:27 | 21.90 | 12.69 |
3 Objetivo da análise
O objetivo da presente análise consiste em identificar o impacto de fatores logísticos e financeiros em avaliações negativas de clientes no e-commerce brasileiro, utilizando dados públicos da plataforma Olist (2016-2018).
Espera-se que fatores logísticos, como atraso na entrega, tenham maior impacto na avaliação negativa do que variáveis financeiras, como valor do pedido e do frete.
A escolha por esta base de dados se deu, principalmente, pelo alinhamento ao meu campo de atuação profissional atual (marketing). Entender o comportamento do consumidor brasileiro no contexto digital é algo de grande interesse para mim.
4 Estudo e limpeza de dados
Descobrindo quantos pedidos foram entregues no total:
pedidos |>
count(order_status) |>
gt()| order_status | n |
|---|---|
| approved | 2 |
| canceled | 625 |
| created | 5 |
| delivered | 96478 |
| invoiced | 314 |
| processing | 301 |
| shipped | 1107 |
| unavailable | 609 |
Filtrando os pedidos com status “delivered”, de modo a iniciar a limpeza da base de dados que não cabem na análise:
delivered = pedidos |>
filter(order_status == "delivered")Identificando quantos dos pedidos entregues possuem reviews:
reviews |>
summarise(total_reviews = n_distinct(order_id)) |>
gt()| total_reviews |
|---|
| 98673 |
Observa-se que há mais reviews do que pedidos entregues. Verificando se há mais de uma review por pedido:
reviews |>
count(order_id) |>
filter(n > 1) |>
head(5) |>
gt()| order_id | n |
|---|---|
| 0035246a40f520710769010f752e7507 | 2 |
| 013056cfe49763c6f66bda03396c5ee3 | 2 |
| 0176a6846bcb3b0d3aa3116a9a768597 | 2 |
| 02355020fd0a40a0d56df9f6ff060413 | 2 |
| 029863af4b968de1e5d6a82782e662f5 | 2 |
Observa-se que há mais de uma review por pedido. Verificando se a review é feita por item ou por pedido:
reviews |>
count(order_id) |>
filter(n > 1) |>
slice(1) |>
gt()| order_id | n |
|---|---|
| 0035246a40f520710769010f752e7507 | 2 |
itens |>
filter(order_id == "0035246a40f520710769010f752e7507") |>
gt()| order_id | order_item_id | product_id | seller_id | shipping_limit_date | price | freight_value |
|---|---|---|---|---|---|---|
| 0035246a40f520710769010f752e7507 | 1 | 8a6187b2665118d5095f99a25fd7ba7a | 4a3ca9315b744ce9f8e9374361493884 | 2017-08-23 01:25:39 | 87 | 12.11 |
itens_por_pedido = itens |>
count(order_id)
reviews_por_pedido = reviews |>
count(order_id)
comparacao = itens_por_pedido |>
left_join(reviews_por_pedido, by = "order_id") |>
filter(n.x == 1 & n.y > 1)
head(comparacao) |>
gt()| order_id | n.x | n.y |
|---|---|---|
| 0035246a40f520710769010f752e7507 | 1 | 2 |
| 013056cfe49763c6f66bda03396c5ee3 | 1 | 2 |
| 0176a6846bcb3b0d3aa3116a9a768597 | 1 | 2 |
| 02355020fd0a40a0d56df9f6ff060413 | 1 | 2 |
| 029863af4b968de1e5d6a82782e662f5 | 1 | 2 |
| 02e0b68852217f5715fb9cc885829454 | 1 | 2 |
Observa-se que o review é feito a nível do pedido e que há mais de uma review por pedido, mesmo para aqueles com 1 único item. Identificando quantos pedidos possuem mais de uma review:
reviews |>
count(order_id) |>
filter(n > 1) |>
summarise(qtd_pedidos = n()) |>
gt()| qtd_pedidos |
|---|
| 547 |
total_pedidos_com_review = reviews |>
distinct(order_id) |>
nrow()
pedidos_com_mais_de_uma_review = reviews |>
count(order_id) |>
filter(n > 1) |>
nrow()
percentual = (pedidos_com_mais_de_uma_review / total_pedidos_com_review) * 100
percentual[1] 0.5543563
Observa-se que os pedidos com mais de uma review representam menos de 1% da base. Verificando se as reviews de um mesmo pedido possuem notas diferentes:
reviews_multiplas = reviews |>
group_by(order_id) |>
filter(n() > 1)comparacao_notas = reviews_multiplas |>
group_by(order_id) |>
summarise(n_notas_distintas = n_distinct(review_score))comparacao_notas |>
count(n_notas_distintas) |>
gt()| n_notas_distintas | n |
|---|---|
| 1 | 345 |
| 2 | 202 |
Observa-se que 202 pedidos tiveram alteração de nota. Filtrando pela última review feita pelo cliente para cada pedido, de modo a evitar duplicação de observações (e aproveitando para remover reviews sem notas):
reviews_unicas = reviews |>
filter(!is.na(.data$review_score)) |>
arrange(order_id, review_answer_timestamp) |>
group_by(order_id) |>
slice_tail(n = 1) |>
ungroup()Como todas as reviews são feitas a nível do pedido, os dados referentes a fatores logísticos e financeiros também precisam estar alinhados a isso. Ajustando a base de itens para o nível do pedido:
itens_agg = itens |>
group_by(order_id) |>
summarise(
total_produtos = n(),
valor_produtos = sum(price),
valor_frete = sum(freight_value),
valor_total = sum(price + freight_value)
)4.1 Resumo da limpeza
- Bases originais
# reviews
# pedidos
# pagamentos
# itens- Bases tratadas:
head(reviews_unicas) |>
gt()| review_id | order_id | review_score | review_comment_title | review_comment_message | review_creation_date | review_answer_timestamp |
|---|---|---|---|---|---|---|
| 97ca439bc427b48bc1cd7177abe71365 | 00010242fe8c5a6d1ba2dd792cb16214 | 5 | NA | Perfeito, produto entregue antes do combinado. | 2017-09-21 | 2017-09-22 10:57:03 |
| 7b07bacd811c4117b742569b04ce3580 | 00018f77f2f0320c557190d7a144bdd3 | 4 | NA | NA | 2017-05-13 | 2017-05-15 11:34:13 |
| 0c5b33dea94867d1ac402749e5438e8b | 000229ec398224ef6ca0657da4fc703e | 5 | NA | Chegou antes do prazo previsto e o produto surpreendeu pela qualidade. Muito satisfatório. | 2018-01-23 | 2018-01-23 16:06:31 |
| f4028d019cb58564807486a6aaf33817 | 00024acbcdf0a6daa1e931b038114c75 | 4 | NA | NA | 2018-08-15 | 2018-08-15 16:39:01 |
| 940144190dcba6351888cafa43f3a3a5 | 00042b26cf59d7ce69dfabb4e55b4fd9 | 5 | NA | Gostei pois veio no prazo determinado . | 2017-03-02 | 2017-03-03 10:54:59 |
| 5e4e50af3b7960b7a10d86ec869509e8 | 00048cc3ae777c65dbb7d2a0634bc1ea | 4 | NA | NA | 2017-05-23 | 2017-05-24 19:00:09 |
head(itens_agg) |>
gt()| order_id | total_produtos | valor_produtos | valor_frete | valor_total |
|---|---|---|---|---|
| 00010242fe8c5a6d1ba2dd792cb16214 | 1 | 58.90 | 13.29 | 72.19 |
| 00018f77f2f0320c557190d7a144bdd3 | 1 | 239.90 | 19.93 | 259.83 |
| 000229ec398224ef6ca0657da4fc703e | 1 | 199.00 | 17.87 | 216.87 |
| 00024acbcdf0a6daa1e931b038114c75 | 1 | 12.99 | 12.79 | 25.78 |
| 00042b26cf59d7ce69dfabb4e55b4fd9 | 1 | 199.90 | 18.14 | 218.04 |
| 00048cc3ae777c65dbb7d2a0634bc1ea | 1 | 21.90 | 12.69 | 34.59 |
head(delivered) |>
gt()| order_id | customer_id | order_status | order_purchase_timestamp | order_approved_at | order_delivered_carrier_date | order_delivered_customer_date | order_estimated_delivery_date |
|---|---|---|---|---|---|---|---|
| e481f51cbdc54678b7cc49136f2d6af7 | 9ef432eb6251297304e76186b10a928d | delivered | 2017-10-02 10:56:33 | 2017-10-02 11:07:15 | 2017-10-04 19:55:00 | 2017-10-10 21:25:13 | 2017-10-18 |
| 53cdb2fc8bc7dce0b6741e2150273451 | b0830fb4747a6c6d20dea0b8c802d7ef | delivered | 2018-07-24 20:41:37 | 2018-07-26 03:24:27 | 2018-07-26 14:31:00 | 2018-08-07 15:27:45 | 2018-08-13 |
| 47770eb9100c2d0c44946d9cf07ec65d | 41ce2a54c0b03bf3443c3d931a367089 | delivered | 2018-08-08 08:38:49 | 2018-08-08 08:55:23 | 2018-08-08 13:50:00 | 2018-08-17 18:06:29 | 2018-09-04 |
| 949d5b44dbf5de918fe9c16f97b45f8a | f88197465ea7920adcdbec7375364d82 | delivered | 2017-11-18 19:28:06 | 2017-11-18 19:45:59 | 2017-11-22 13:39:59 | 2017-12-02 00:28:42 | 2017-12-15 |
| ad21c59c0840e6cb83a9ceb5573f8159 | 8ab97904e6daea8866dbdbc4fb7aad2c | delivered | 2018-02-13 21:18:39 | 2018-02-13 22:20:29 | 2018-02-14 19:46:34 | 2018-02-16 18:17:02 | 2018-02-26 |
| a4591c265e18cb1dcee52889e2d8acc3 | 503740e9ca751ccdda7ba28e9ab8f608 | delivered | 2017-07-09 21:57:05 | 2017-07-09 22:10:13 | 2017-07-11 14:58:04 | 2017-07-26 10:57:55 | 2017-08-01 |
- Base final analítica:
df = delivered |>
left_join(reviews_unicas, by = "order_id") |>
left_join(itens_agg, by = "order_id")
head(df) |>
gt()| order_id | customer_id | order_status | order_purchase_timestamp | order_approved_at | order_delivered_carrier_date | order_delivered_customer_date | order_estimated_delivery_date | review_id | review_score | review_comment_title | review_comment_message | review_creation_date | review_answer_timestamp | total_produtos | valor_produtos | valor_frete | valor_total |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| e481f51cbdc54678b7cc49136f2d6af7 | 9ef432eb6251297304e76186b10a928d | delivered | 2017-10-02 10:56:33 | 2017-10-02 11:07:15 | 2017-10-04 19:55:00 | 2017-10-10 21:25:13 | 2017-10-18 | a54f0611adc9ed256b57ede6b6eb5114 | 4 | NA | Não testei o produto ainda, mas ele veio correto e em boas condições. Apenas a caixa que veio bem amassada e danificada, o que ficará chato, pois se trata de um presente. | 2017-10-11 | 2017-10-12 03:43:48 | 1 | 29.99 | 8.72 | 38.71 |
| 53cdb2fc8bc7dce0b6741e2150273451 | b0830fb4747a6c6d20dea0b8c802d7ef | delivered | 2018-07-24 20:41:37 | 2018-07-26 03:24:27 | 2018-07-26 14:31:00 | 2018-08-07 15:27:45 | 2018-08-13 | 8d5266042046a06655c8db133d120ba5 | 4 | Muito boa a loja | Muito bom o produto. | 2018-08-08 | 2018-08-08 18:37:50 | 1 | 118.70 | 22.76 | 141.46 |
| 47770eb9100c2d0c44946d9cf07ec65d | 41ce2a54c0b03bf3443c3d931a367089 | delivered | 2018-08-08 08:38:49 | 2018-08-08 08:55:23 | 2018-08-08 13:50:00 | 2018-08-17 18:06:29 | 2018-09-04 | e73b67b67587f7644d5bd1a52deb1b01 | 5 | NA | NA | 2018-08-18 | 2018-08-22 19:07:58 | 1 | 159.90 | 19.22 | 179.12 |
| 949d5b44dbf5de918fe9c16f97b45f8a | f88197465ea7920adcdbec7375364d82 | delivered | 2017-11-18 19:28:06 | 2017-11-18 19:45:59 | 2017-11-22 13:39:59 | 2017-12-02 00:28:42 | 2017-12-15 | 359d03e676b3c069f62cadba8dd3f6e8 | 5 | NA | O produto foi exatamente o que eu esperava e estava descrito no site e chegou bem antes da data prevista. | 2017-12-03 | 2017-12-05 19:21:58 | 1 | 45.00 | 27.20 | 72.20 |
| ad21c59c0840e6cb83a9ceb5573f8159 | 8ab97904e6daea8866dbdbc4fb7aad2c | delivered | 2018-02-13 21:18:39 | 2018-02-13 22:20:29 | 2018-02-14 19:46:34 | 2018-02-16 18:17:02 | 2018-02-26 | e50934924e227544ba8246aeb3770dd4 | 5 | NA | NA | 2018-02-17 | 2018-02-18 13:02:51 | 1 | 19.90 | 8.72 | 28.62 |
| a4591c265e18cb1dcee52889e2d8acc3 | 503740e9ca751ccdda7ba28e9ab8f608 | delivered | 2017-07-09 21:57:05 | 2017-07-09 22:10:13 | 2017-07-11 14:58:04 | 2017-07-26 10:57:55 | 2017-08-01 | 89b738e70a1ce346db29a20fb2910161 | 4 | NA | NA | 2017-07-27 | 2017-07-27 22:48:30 | 1 | 147.90 | 27.36 | 175.26 |
5 Análise descritiva
5.1 Panorama geral das reviews (sentimento)
Esta parte da análise é dedicada a contextualizar o comportamento geral da variável numérica discreta “notas” e os sentimentos representados por ela.
Considerando:
Reviews negativas = nota igual ou abaixo de 2
Reviews neutras = nota 3
Reviews positivas = nota igual ou acima de 4
Gráfico de barras para observação da distribuição dos sentimentos das reviews:
# Criando as variáveis categóricas
df = df |>
mutate(
categoria_nota = factor(
case_when(
review_score <= 2 ~ "Negativa",
review_score == 3 ~ "Neutra",
review_score >= 4 ~ "Positiva"
),
levels = c("Negativa", "Neutra", "Positiva")
))# Criando o gráfico
df |>
filter(!is.na(categoria_nota)) |>
ggplot(aes(x = categoria_nota, fill = categoria_nota)) +
geom_bar() +
scale_fill_manual(values = c(
"Negativa" = "#d73027",
"Neutra" = "#fee08b",
"Positiva" = "#1a9850"
)) +
theme_minimal() +
labs (
x = "Sentimento da review",
y = "Frequência",
title = "Distribuição do sentimento das avaliações",
subtitle = "Base de dados: df"
) +
theme(legend.position = "none")Pode-se calcular a proporção das notas negativas:
df |>
summarise(
prop_negativas = round((sum(review_score <= 2, na.rm = TRUE) / n()) * 100)
) |>
gt()| prop_negativas |
|---|
| 13 |
Observa-se que as reviews negativas representam cerca de 13% do total de reviews com notas.
5.1.1 Diagnóstico geral do sentimento das reviews
Majoritariamente positivo
Com minoria negativa, mas suficiente para análise de impacto
5.2 Impacto de fatores logísticos
Esta parte da análise dedica-se a compreender se fatores logísticos influenciam a probabilidade de uma avaliação negativa dentre os pedidos entregues.
Variáveis logísticas consideradas para essa análise:
- Atraso na entrega: variável binária que responde se houve atraso na entrega ou não
df = df |>
mutate(
order_delivered_customer_date = as.Date(order_delivered_customer_date),
order_estimated_delivery_date = as.Date(order_estimated_delivery_date),
atraso_dias = as.numeric(order_delivered_customer_date - order_estimated_delivery_date),
entrega_atrasada = atraso_dias > 0
)- Tempo de entrega: variável que contabiliza os dias desde a confirmação da compra até a entrega
df = df |>
mutate(
order_approved_at = as.Date(order_approved_at),
tempo_entrega = as.numeric(order_delivered_customer_date - order_approved_at)
)Descrição estatística para contextualizar o comportamento geral destas variáveis:
df |>
dplyr::select(atraso_dias, tempo_entrega) |>
summarytools::descr()Descriptive Statistics
df
N: 96478
atraso_dias tempo_entrega
----------------- ------------- ---------------
Mean -11.88 11.98
Std.Dev 10.18 9.53
Min -147.00 -7.00
Q1 -17.00 6.00
Median -12.00 10.00
Q3 -7.00 15.00
Max 188.00 208.00
MAD 7.41 5.93
IQR 10.00 9.00
CV -0.86 0.79
Skewness 2.02 3.86
SE.Skewness 0.01 0.01
Kurtosis 28.07 39.79
N.Valid 96470.00 96456.00
N 96478.00 96478.00
Pct.Valid 99.99 99.98
# Criando função para calcular normalidade
plot_normalidade = function(dados, var, bins = 30, xlim = NULL){
var_enquo = rlang::enquo(var)
vetor = dados |> dplyr::pull(!!var_enquo)
media = mean(vetor, na.rm = TRUE)
mediana = median(vetor, na.rm = TRUE)
p1 = dados |>
ggplot(aes(x = !!var_enquo)) +
geom_histogram(
aes(y = after_stat(density)),
bins = bins,
fill = "lightblue",
color = "black"
) +
geom_density(color = "darkblue", linewidth = 0.8, alpha = 0.3) +
theme_minimal() +
labs(
title = paste0("Distribuição - ", rlang::as_name(var_enquo)),
x = rlang::as_name(var_enquo),
y = "Densidade"
)
# aplicar limite do eixo x se for especificado
if(!is.null(xlim)){
p1 = p1 + coord_cartesian(xlim = xlim)
}
p2 = dados |>
ggplot(aes(sample = !!var_enquo)) +
stat_qq(size = 2, alpha = 0.6) +
stat_qq_line(color = "red", linewidth = 1) +
theme_minimal() +
labs(
title = paste0("QQ plot - ", rlang::as_name(var_enquo)),
x = "Quantis teóricos",
y = "Quantis amostrais"
)
p1 + p2
}df |>
plot_normalidade(atraso_dias, bins = 75, xlim = c(-60, 60))df |>
plot_normalidade(tempo_entrega, bins = 60, xlim = c(-10, 60))OBS: A quantidade de bins escolhida para ambos os histogramas foi o valor encontrado que melhor permite a visualização da distribuição das observações.
df |>
filter(!is.na(entrega_atrasada)) |>
ggplot(aes(x = entrega_atrasada, fill = entrega_atrasada)) +
geom_bar() +
scale_fill_manual(values = c(
"FALSE" = "#d73027",
"TRUE" = "#1a9850"
)) +
theme_minimal() +
labs (
x = "Entrega atrasada?",
y = "Frequência",
title = "Frequência de entregas atrasadas",
subtitle = "Base de dados: df"
) +
theme(legend.position = "none")O histograma e o QQ plot indicam que atraso_dias não segue distribuição normal, com forte concentração de valores próximos de zero e presença de alguns valores extremos. A mediana de -12 dias indica que a maioria dos pedidos apresenta atraso baixo ou inexistente. O IQR foi de cerca de 10 dias, representando a dispersão dos 50% centrais dos atrasos observados.
O gráfico de barras confirma o resultado da mediana, indicando que entregas atrasadas representam menos de 10% das observações.
Já a variável tempo_entrega apresenta assimetria à direita, com maior concentração de valores baixos e cauda longa à direita. A mediana foi de 10 dias, indicando o prazo típico de entrega. O IQR foi de cerca de 9 dias, descrevendo a variabilidade dos tempos de entrega mais comuns sem grande influência de valores extremos.
- Comparando a proporção de reviews negativas vs atraso: quando há atraso, aumenta a chance de avaliação negativa?
df |>
mutate(faixa_atraso = floor(atraso_dias/5)*5) |>
group_by(faixa_atraso) |>
summarise(media_review = mean(review_score, na.rm = TRUE)) |>
ggplot(aes(x = faixa_atraso, y = media_review)) +
geom_line(linewidth = 1.2, color = "red") +
theme_minimal() +
labs(
title = "Nota média da review por tempo de atraso",
x = "Tempo de atraso (dias)",
y = "Nota média"
)df |>
filter(
!is.na(entrega_atrasada),
!is.na(categoria_nota)
) |>
group_by(entrega_atrasada) |>
summarise(
prop_negativas = mean(categoria_nota == "Negativa"),
total = n()
) |>
gt()| entrega_atrasada | prop_negativas | total |
|---|---|---|
| FALSE | 0.09267355 | 89443 |
| TRUE | 0.62419683 | 6381 |
ggplot(df |>
filter(!is.na(entrega_atrasada), !is.na(categoria_nota)) |>
group_by(entrega_atrasada) |>
summarise(prop_negativas = mean(categoria_nota == "Negativa")),
aes(x = entrega_atrasada, y = prop_negativas, fill = entrega_atrasada)) +
geom_col() +
scale_fill_manual(values = c("FALSE" = "red", "TRUE" = "green")) +
labs(
title = "Proporção de avaliações negativas por atraso",
subtitle = "Base de dados: df",
x = "Entrega atrasada?",
y = "Proporção de avaliações negativas",
fill = "Entrega atrasada?"
) +
theme(legend.position = "none")Observa-se que, quando não há atraso na entrega, a proporção de avaliações negativas é de aproximadamente 9%. No entanto, quando ocorre atraso, essa proporção sobe para cerca de 62%, indicando um aumento expressivo na probabilidade de insatisfação. Esse resultado sugere possível associação entre atrasos logísticos e avaliações negativas dos clientes.
- Comparando tempo de entrega vs reviews: entregas mais demoradas, mesmo dentro do prazo, geram mais avaliações negativas?
df |>
mutate(faixa_entrega = floor(tempo_entrega/5)*5) |>
group_by(faixa_entrega) |>
summarise(media_review = mean(review_score, na.rm = TRUE)) |>
ggplot(aes(x = faixa_entrega, y = media_review)) +
geom_line(linewidth = 1.2, color = "red") +
theme_minimal() +
labs(
title = "Nota média da review por tempo de entrega",
x = "Tempo de entrega (dias)",
y = "Nota média"
)df |>
filter(!is.na(categoria_nota)) |>
group_by(categoria_nota) |>
summarise(
media_tempo = mean(tempo_entrega, na.rm = TRUE),
mediana_tempo = median(tempo_entrega, na.rm = TRUE)
) |>
gt()| categoria_nota | media_tempo | mediana_tempo |
|---|---|---|
| Negativa | 19.61177 | 15 |
| Neutra | 13.65774 | 11 |
| Positiva | 10.51855 | 9 |
ggplot(df |>
group_by(categoria_nota) |>
filter(!is.na(categoria_nota)) |>
summarise(media_tempo = mean(tempo_entrega, na.rm = TRUE)),
aes(x = categoria_nota, y = media_tempo, fill = categoria_nota)) +
geom_col() +
scale_fill_manual(values = c(
"Negativa" = "red",
"Neutra" = "yellow",
"Positiva" = "green"
)) +
theme_minimal() +
labs(
title = "Tempo médio de entrega por categoria de avaliação",
subtitle = "Base de dados: df",
x = "Categoria da avaliação",
y = "Tempo médio de entrega (dias)"
) +
theme(legend.position = "none")Observa-se um aumento consistente no tempo médio de entrega conforme a avaliação se torna mais negativa. Pedidos avaliados negativamente apresentaram tempo médio de 19,6 dias, enquanto pedidos com avaliação positiva apresentaram média de 10,5 dias. Esse padrão sugere que entregas mais demoradas estão associadas a maior insatisfação do cliente, mesmo quando não configuram necessariamente atraso formal.
5.2.1 Diagnóstico do impacto de fatores logísticos
A análise evidencia que pedidos entregues com atraso apresentam maior incidência de avaliações negativas, indicando que o desempenho logístico pode influenciar diretamente a satisfação do cliente. Mesmo entre as entregas que ocorrem dentro do prazo, quanto maior o tempo de entrega, maior a incidência de avaliações negativas.
5.3 Impacto de fatores financeiros
Esta parte da análise dedica-se a compreender se fatores financeiros influenciam a probabilidade de uma avaliação negativa dentre os pedidos entregues.
Variáveis financeiras consideradas para essa análise:
- Preço do frete: variável numérica que corresponde ao valor pago pelo consumidor para o frete do pedido
dfSummary(df |> select(valor_frete))Data Frame Summary
df
Dimensions: 96478 x 1
Duplicates: 88609
------------------------------------------------------------------------------------------------
No Variable Stats / Values Freqs (% of Valid) Graph Valid Missing
---- ------------- ------------------------- ---------------------- ------- ---------- ---------
1 valor_frete Mean (sd) : 22.8 (21.6) 7476 distinct values : 96478 0
[numeric] min < med < max: : (100.0%) (0.0%)
0 < 17.2 < 1795 :
IQR (CV) : 10.2 (0.9) :
:
------------------------------------------------------------------------------------------------
- Preço do(s) produto(s): variável numérica que corresponde ao valor pago pelo consumidor pelo(s) produto(s)
dfSummary(df |> select(valor_produtos))Data Frame Summary
df
Dimensions: 96478 x 1
Duplicates: 88844
-------------------------------------------------------------------------------------------------
No Variable Stats / Values Freqs (% of Valid) Graph Valid Missing
---- ---------------- ----------------------- ---------------------- ------- ---------- ---------
1 valor_produtos Mean (sd) : 137 (209) 7435 distinct values : 96478 0
[numeric] min < med < max: : (100.0%) (0.0%)
0.8 < 86.6 < 13440 :
IQR (CV) : 104 (1.5) :
:
-------------------------------------------------------------------------------------------------
Essas variáveis refletem custos diretos da compra e podem influenciar a percepção de valor da transação e, consequentemente, a avaliação atribuída pelos clientes.
Descrição estatística para contextualizar o comportamento geral destas variáveis:
df |>
plot_normalidade(valor_frete, bins = 240, xlim = c(-10, 100))df |>
plot_normalidade(valor_produtos, bins = 250, xlim = c(-10, 1000))OBS: A quantidade de bins escolhida para ambos os histogramas foi o valor encontrado que melhor permite a visualização da distribuição das observações.
O histograma e o QQ plot indicam que valor_produto não segue distribuição normal, apresentando assimetria à direita, com maior concentração de valores mais baixos e uma cauda longa à direita. A mediana de aproximadamente 86,6 reais indica que metade dos pedidos possui valor de produto até esse montante. O IQR de cerca de 104 reais mostra uma dispersão relativamente ampla entre os 50% centrais dos valores, sugerindo grande variabilidade no preço dos produtos vendidos.
Já a variável valor_frete também apresenta assimetria à direita, com concentração em valores menores e presença de alguns valores mais altos. A mediana foi de aproximadamente 17,2 reais, indicando que metade dos pedidos não ultrapassam este montante no valor do frete. O IQR de cerca de 10,2 reais descreve a variabilidade dos valores de frete mais comuns, mostrando que a maioria das entregas apresenta custos relativamente próximos desse intervalo central.
- Comparando a proporção de reviews negativas vs valor do produto: pedidos mais caros recebem mais avaliações negativa?
df |>
group_by(categoria_nota) |>
filter(!is.na(categoria_nota)) |>
summarise(
media_valor_produtos = round(mean(valor_produtos, na.rm = TRUE), 2),
mediana_valor_produtos = median(valor_produtos, na.rm = TRUE),
n = n()
) |>
gt()| categoria_nota | media_valor_produtos | mediana_valor_produtos | n |
|---|---|---|---|
| Negativa | 159.89 | 98.00 | 12273 |
| Neutra | 127.48 | 82.99 | 7916 |
| Positiva | 134.03 | 84.94 | 75643 |
Observa-se que pedidos com avaliações negativas apresentam valor médio de produtos ligeiramente superior aos pedidos com avaliações neutras ou positivas. A média dos pedidos avaliados negativamente foi de aproximadamente 159,89 reais, enquanto pedidos com avaliações positivas apresentaram média de 134,03 reais.
Apesar dessa diferença, os valores medianos são relativamente próximos, indicando que o valor dos produtos pode apresentar alguma associação com avaliações negativas, mas não configura um fator fortemente determinante para a insatisfação dos clientes.
- Comparando a proporção de reviews negativas vs valor do frete: fretes mais caros aumentam a chance de avaliação negativa?
df |>
group_by(categoria_nota) |>
filter(!is.na(categoria_nota)) |>
summarise(
media_valor_frete = round(mean(valor_frete, na.rm = TRUE), 2),
mediana_valor_frete = median(valor_frete, na.rm = TRUE),
n = n()
) |>
gt()| categoria_nota | media_valor_frete | mediana_valor_frete | n |
|---|---|---|---|
| Negativa | 27.71 | 18.49 | 12273 |
| Neutra | 23.56 | 17.63 | 7916 |
| Positiva | 21.88 | 16.87 | 75643 |
Padrão semelhante ao de valor do produto é observado para o valor do frete. Tanto a média quanto a mediana são levemente mais altas em avaliações negativas, porém as diferenças são pequenas, sugerindo que fatores financeiros não exercem influência relevante sobre o sentimento das reviews.
5.3.1 Diagnóstico do impacto de fatores financeiros
A análise evidencia que pedidos com reviews negativas apresentam, em média, valores de produto e de frete ligeiramente mais altos em comparação às demais avaliações. No entanto, como a diferença observada é pequena, não há evidências suficientes para afirmar que fatores financeiros impactam de forma relevante o sentimento das reviews.
6 Conclusão
A análise realizada sugere que fatores logísticos, como tempo de entrega e atrasos, podem estar associados à ocorrência de reviews negativas. Por outro lado, fatores financeiros, como valor do frete e valor total da compra, não apresentaram evidências claras de influência sobre as avaliações dos consumidores.
- Análise de correlação para confirmar os resultados:
num_var = df |>
select(where(is.numeric))
matriz_cor_pedidos = cor(num_var, use = "complete.obs")
corrplot(
matriz_cor_pedidos,
method = "color",
type = "upper",
addCoef.col = "gray",
tl.col = "black",
tl.srt = 45
)Através da matriz de correlação acima, observa-se que os valores mais positivos são aqueles mais obviamente correlacionados, como o tempo de entrega e o tempo de atraso, o valor do frete e o valor total do pedido, o valor total dos produtos e o valor do frete, bem como a quantidade de produtos de um pedido e o valor do frete.
Os três pares de variáveis mais correlacionados são:
tempo_entrega e atraso_dias (r = 0.60)
valor_total e valor_frete (r = 0.49)
total_produtos e valor_frete (r = 0.41)
Já os valores mais negativos correspondem à correlação entre o tempo de entrega e a nota da review, bem como entre o tempo de atraso e a nota da review. A matriz indica que fatores logísticos, como maior tempo de entrega e maiores atrasos, estão associados a notas de avaliação mais baixas. Trata-se de uma correlação fraca (magnitude entre 0,20 e 0,39), mas ainda superior à observada para fatores financeiros, como valor do frete e valor total dos produtos.
df |>
ggplot(aes(x = tempo_entrega, y = review_score)) +
geom_jitter(alpha = 0.1, height = 0.1) +
geom_smooth(method = "lm", color = "red") +
theme_minimal() +
labs(
title = "Relação entre tempo de entrega e nota da review",
subtitle = "Base de dados: df",
x = "Tempo de entrega (dias)",
y = "Nota da review"
)df |>
ggplot(aes(x = atraso_dias, y = review_score)) +
geom_jitter(alpha = 0.1, height = 0.1) +
geom_smooth(method = "lm", color = "red") +
theme_minimal() +
labs(
title = "Relação entre tempo de atraso e nota da review",
subtitle = "Base de dados: df",
x = "Tempo de atraso (dias)",
y = "Nota da review"
)Os scatterplots acima, entre tempo de entrega/tempo de atraso e nota da avaliação, mostram uma tendência negativa, evidenciada pela linha de regressão. Embora a dispersão dos pontos seja alta, observa-se que pedidos com maior tempo de entrega e tempo de atraso tendem a receber avaliações menores. A visualização apresenta faixas horizontais devido ao fato de a variável de nota ser discreta (valores de 1 a 5), o que limita a visualização direta da correlação.
Os resultados indicam que fatores logísticos, como tempo de entrega e atrasos, estão associados a avaliações mais baixas dos consumidores. Assim, melhorias na eficiência do frete podem contribuir para reduzir reviews negativas e melhorar a experiência do cliente no e-commerce.