Relatório da Pelican Stores

Autor

Izan Cassio Nascimento Pereira

Data de Publicação

15 de maio de 2025

1 Avaliação dos dados da Pelican Stores

Iniciaremos uma avaliação de alguns dados da empresa Pelican Stores, com o intuito de identificar quem são os principais clientes (idade, sexo, tipo de cartão, etc.), quando possível, avaliar o desempenho das vendas por produto, loja e forma de pagamento, verificar o impacto de descontos e se há recorrência de compras, em caso de dados suficientes definir um painel com indicadores-chave (KPI) para tomada de decisão e estimar vendas futuras.

#Lendo os dados
pelican <- read.csv('PelicanStores.CSV', sep = ';', dec = ',')
#View(pelican)

pelican <- pelican |>
  mutate(across(where(is.character), as.factor))
str(pelican)
'data.frame':   100 obs. of  8 variables:
 $ Cliente                  : int  1 2 3 4 5 6 7 8 9 10 ...
 $ Tipo.de.Cliene           : Factor w/ 2 levels "Promotional",..: 2 1 2 1 2 2 1 2 1 2 ...
 $ Numero.de.Itens.Comprados: int  1 1 1 5 2 1 2 1 2 1 ...
 $ Venda.Liquidas           : num  39.5 102.4 22.5 100.4 54 ...
 $ Metodo.de.Pagamento      : Factor w/ 5 levels "American Express",..: 2 4 4 4 3 3 4 5 4 4 ...
 $ Genero                   : Factor w/ 2 levels "Female","Male": 2 2 2 2 2 2 2 2 2 2 ...
 $ Estado.civil             : Factor w/ 2 levels "Married","Single": 1 1 1 1 1 1 1 1 1 1 ...
 $ Idade                    : int  32 36 32 28 34 44 30 40 46 36 ...
pelican$Numero.de.Itens.Comprados <- as.factor(pelican$Numero.de.Itens.Comprados)
str(pelican)
'data.frame':   100 obs. of  8 variables:
 $ Cliente                  : int  1 2 3 4 5 6 7 8 9 10 ...
 $ Tipo.de.Cliene           : Factor w/ 2 levels "Promotional",..: 2 1 2 1 2 2 1 2 1 2 ...
 $ Numero.de.Itens.Comprados: Factor w/ 12 levels "1","2","3","4",..: 1 1 1 5 2 1 2 1 2 1 ...
 $ Venda.Liquidas           : num  39.5 102.4 22.5 100.4 54 ...
 $ Metodo.de.Pagamento      : Factor w/ 5 levels "American Express",..: 2 4 4 4 3 3 4 5 4 4 ...
 $ Genero                   : Factor w/ 2 levels "Female","Male": 2 2 2 2 2 2 2 2 2 2 ...
 $ Estado.civil             : Factor w/ 2 levels "Married","Single": 1 1 1 1 1 1 1 1 1 1 ...
 $ Idade                    : int  32 36 32 28 34 44 30 40 46 36 ...

Como estamos tratando de dados em que sua estrutura character, precisamos fazer uma manipulação e transformar em factor.

2 Análise gráfica dos dados

ggplot(data = pelican, aes(x = Idade)) +
  geom_histogram(binwidth = 7, fill = "green", alpha = 0.7) +
  labs(title = "Perfil do cliente por Idade", x = "Idade", y = "Frequência") +
  theme_minimal()

Como observamos, a idade dos clientes dessa loja esta entre 30 à 60 anos, com uma frequência maior entre os 35 e 55.

vendas_tipo <- pelican |>
  group_by(Tipo.de.Cliene) |>
  summarise(Vendas = sum(Venda.Liquidas, na.rm = TRUE))
ggplot(vendas_tipo, aes(x = Tipo.de.Cliene, y = Vendas, fill = Tipo.de.Cliene)) +
  geom_bar(stat = "identity") +
  labs(title = "Vendas Líquidas por Tipo de Cliente",
       x = "Tipo de Cliente",
       y = "Vendas Líquidas ($)") +
  theme_minimal()

Temos observado que para esta loja, as vendas de itens em promoção, tem sido maior que as vendas regulares.

vendas_metodo <- pelican |>
  group_by(Metodo.de.Pagamento) |>
  summarise(Vendas = sum(Venda.Liquidas, na.rm = TRUE))
ggplot(vendas_metodo, aes(x = Metodo.de.Pagamento, y = Vendas, fill = Metodo.de.Pagamento)) +
  geom_bar(stat = "identity") +
  labs(title = "Vendas Líquidas por Metodo de Pagamento",
       x = "Metodo de Pagamento",
       y = "Vendas Líquidas ($)") +
  theme_minimal()

Neste vemos que quase todas as vendas ocorreram com clientes que utilizando o Proprietary Card para efetuar suas compras.

vendas_genero <- pelican |>
  group_by(Genero) |>
  summarise(Vendas = sum(Venda.Liquidas, na.rm = TRUE))
ggplot(vendas_genero, aes(x = Genero, y = Vendas, fill = Genero)) +
  geom_bar(stat = "identity") +
  labs(title = "Vendas Líquidas por Gênero do Cliente",
       x = "Genero do Cliente",
       y = "Vendas Líquidas ($)") +
  theme_minimal()

As mulheres tendem a comprar mais que os homens.

ggplot(data = pelican, aes(x = Genero, fill = Metodo.de.Pagamento)) +
  geom_bar(position = "dodge") +
  labs(title = "Avaliando a forma de pagamento por gênero",
       x = "Gênero", y = "Contagem") +
  theme_minimal()

Aqui já podemos observar que mais da metade das mulheres utilizam o cartão Proprietary Card, sendo elas as que mais compraram.

ggplot(data = pelican, aes(x = Tipo.de.Cliene, fill = Metodo.de.Pagamento)) +
  geom_bar(position = "dodge") +
  labs(title = "Avaliando pagamento por Tipo de Cliente",
       x = "Tipo de Cliente", y = "Contagem") +
  theme_minimal()

Como já observado quando avaliamos o metodo de pagamento pelo Tipo, vimos que os clientes Promotional gastam mais no Propritary Card, mas, isso também se repete nos clientes Regular.

Talvez por ter um volume maior de clientes com esse tipo de cartão, explica o volume de itens, valor gasto…

ggplot(data = pelican, aes(x = Genero, fill = Numero.de.Itens.Comprados)) +
  geom_bar(position = "dodge") +
  labs(title = "Quantidade de Produto por Genero",
       x = "Gênero", y = "Contagem") +
  theme_minimal()

Os itens 1 e 2, foram os mais comprados entre os generos.

ggplot(data = pelican, aes(x = Tipo.de.Cliene, fill = Numero.de.Itens.Comprados)) +
  geom_bar(position = "dodge") +
  labs(title = "Quantidade de Produto por Tipo",
       x = "Tipo de Cliente", y = "Contagem") +
  theme_minimal()

Quando olhamos somente o tipo do cliente pelo item, o cenário de compra continua o mesmo, itens 1 e 2 sendo o mais comprado, dentre eles o 2 é o item mais procurado.

ggplot(data = pelican, aes(x = Metodo.de.Pagamento, fill = Numero.de.Itens.Comprados)) +
  geom_bar(position = "dodge") +
  labs(title = "Quantidade de Produto por Pagamento",
       x = "Metodo de Pagamento", y = "Contagem") +
  theme_minimal()

Agora quando pegamos esses itens e olhamos para o metodo de pagamento, vemos que o item 1 se sobresai no cartão Proprietary Card.

3 Modelagem Utilizando Árvore de decisão e KNN

pelican <- pelican |>
  select(Tipo.de.Cliene,Numero.de.Itens.Comprados,Metodo.de.Pagamento,Venda.Liquidas,Genero, Idade)
head(pelican)
  Tipo.de.Cliene Numero.de.Itens.Comprados Metodo.de.Pagamento Venda.Liquidas
1        Regular                         1            Discover           39.5
2    Promotional                         1    Proprietary Card          102.4
3        Regular                         1    Proprietary Card           22.5
4    Promotional                         5    Proprietary Card          100.4
5        Regular                         2          MasterCard           54.0
6        Regular                         1          MasterCard           44.5
  Genero Idade
1   Male    32
2   Male    36
3   Male    32
4   Male    28
5   Male    34
6   Male    44
pelicannormalizados <- pelican |>
  mutate(across(c(Venda.Liquidas), scale))

pelicannormalizados <- na.omit(pelicannormalizados)
set.seed(1910)

Dadosnormalizados <- pelicannormalizados[sample(1:nrow(pelicannormalizados)), ]

n <- round(0.75 * nrow(Dadosnormalizados))
n
[1] 75
treino <- Dadosnormalizados[1:n, ]
teste <- Dadosnormalizados[-(1:n), ]

Como a variavel Venda Liquida é continua, para utilizarmos ela como uma resposta, temos que utilizar anova como metodo.

arvore.dados1 <- rpart(formula = Venda.Liquidas ~., data = treino, method = "anova")
rpart.plot(arvore.dados1, extra = 101)

previsao.arvore1 <- predict(arvore.dados1, newdata = teste, type = "vector")
head(previsao.arvore1)
         13          46          52          31          28           5 
 1.04393455 -0.08723724  1.04393455 -0.47292786  1.04393455 -0.47292786 
real <- teste$Venda.Liquidas
media <- mean(abs(previsao.arvore1 - real))
rmse <- sqrt(mean((previsao.arvore1 - real)^2))
r2 <- 1 - sum((previsao.arvore1 - real)^2) / sum((real - mean(real))^2)

cat("Erro Absoluto:", media, "\nRMSE:", rmse, "\nR²:", r2, "\n")
Erro Absoluto: 0.428078 
RMSE: 0.6226273 
R²: 0.5934892 
arvore.dados2 <- rpart(formula = Tipo.de.Cliene ~., data = treino, method = "class")
rpart.plot(arvore.dados2, extra = 101)

previsao.arvore2 <- predict(arvore.dados2, newdata = teste, type = "class")
mean(previsao.arvore2 == teste$Tipo.de.Cliene)
[1] 0.76
tabela.previsao.arvore2 <- table(previsao.arvore2, teste$Tipo.de.Cliene) # matriz de confusão
tabela.previsao.arvore2
                
previsao.arvore2 Promotional Regular
     Promotional          15       1
     Regular               5       4
arvore.dados3 <- rpart(formula = Genero ~., data = treino, method = "class")
rpart.plot(arvore.dados3, extra = 101)

previsao.arvore3 <- predict(arvore.dados3, newdata = teste, type = "class")
mean(previsao.arvore3 == teste$Genero)
[1] 0.6
arvore.dados4 <- rpart(formula = Numero.de.Itens.Comprados ~., data = treino, method = "class")
previsao.arvore4 <- predict(arvore.dados4, newdata = teste, type = "class")
mean(previsao.arvore4 == teste$Numero.de.Itens.Comprados)
[1] 0.6
tabela.previsao.arvore4 <- table(previsao.arvore4, teste$Numero.de.Itens.Comprados) # matriz de confusão
tabela.previsao.arvore4
                
previsao.arvore4 1 2 3 4 5 6 7 8 9 10 13 17
              1  7 2 0 0 0 0 0 0 0  0  0  0
              2  0 7 1 1 0 0 0 0 0  0  0  0
              3  0 0 0 0 0 0 0 0 0  0  0  0
              4  1 0 1 1 0 0 0 0 0  0  0  0
              5  0 0 0 0 0 0 0 0 0  0  0  0
              6  0 0 0 0 2 0 0 0 2  0  0  0
              7  0 0 0 0 0 0 0 0 0  0  0  0
              8  0 0 0 0 0 0 0 0 0  0  0  0
              9  0 0 0 0 0 0 0 0 0  0  0  0
              10 0 0 0 0 0 0 0 0 0  0  0  0
              13 0 0 0 0 0 0 0 0 0  0  0  0
              17 0 0 0 0 0 0 0 0 0  0  0  0
rpart.plot(arvore.dados4, extra = 101)

modelo1 <- knn(train = treino[,c(2,4)],
               test = teste[,c(2,4)],
               cl = treino$Tipo.de.Cliene,
               k = 2)
modelo1
 [1] Promotional Regular     Promotional Promotional Regular     Promotional
 [7] Promotional Regular     Regular     Promotional Regular     Regular    
[13] Promotional Promotional Regular     Regular     Regular     Regular    
[19] Promotional Regular     Regular     Regular     Promotional Regular    
[25] Promotional
Levels: Promotional Regular
mean(modelo1 == teste$Tipo.de.Cliene)
[1] 0.48
table(modelo1, teste$Tipo.de.Cliene)
             
modelo1       Promotional Regular
  Promotional           9       2
  Regular              11       3
modelo2 <- knn(train = treino[,c(2,4)],
               test = teste[,c(2,4)],
               cl = treino$Tipo.de.Cliene,
               k = 3)
modelo2
 [1] Promotional Promotional Promotional Promotional Promotional Promotional
 [7] Promotional Regular     Promotional Promotional Regular     Promotional
[13] Promotional Promotional Regular     Promotional Promotional Regular    
[19] Promotional Promotional Regular     Regular     Regular     Regular    
[25] Regular    
Levels: Promotional Regular
mean(modelo2 == teste$Tipo.de.Cliene)
[1] 0.68
table(modelo2, teste$Tipo.de.Cliene)
             
modelo2       Promotional Regular
  Promotional          14       2
  Regular               6       3
ControleKNN <- trainControl(method = "cv", number = 10)
Crossvalidation <- train(Tipo.de.Cliene ~., data = treino, method = "knn", trControl = ControleKNN)
Crossvalidation$results
  k  Accuracy        Kappa AccuracySD   KappaSD
1 5 0.6142857 -0.041221719  0.1111040 0.2455852
2 7 0.6160714 -0.004210112  0.1713314 0.3537024
3 9 0.6142857 -0.008959276  0.1499244 0.3527443
modelo3 <- knn(train = treino[,c(2,4)],
               test = teste[,c(2,4)],
               cl = treino$Tipo.de.Cliene,
               k = 4)
modelo3
 [1] Promotional Regular     Promotional Promotional Promotional Promotional
 [7] Promotional Regular     Promotional Promotional Promotional Promotional
[13] Promotional Promotional Regular     Promotional Promotional Regular    
[19] Promotional Regular     Regular     Regular     Promotional Regular    
[25] Promotional
Levels: Promotional Regular
mean(modelo3 == teste$Tipo.de.Cliene)
[1] 0.72
table(modelo3, teste$Tipo.de.Cliene)
             
modelo3       Promotional Regular
  Promotional          15       2
  Regular               5       3
modelo4 <- knn(train = treino[,c(2,4)],
               test = teste[,c(2,4)],
               cl = treino$Tipo.de.Cliene,
               k = 5)
modelo4
 [1] Promotional Promotional Promotional Promotional Promotional Promotional
 [7] Promotional Regular     Promotional Promotional Regular     Promotional
[13] Promotional Promotional Regular     Promotional Regular     Regular    
[19] Promotional Promotional Regular     Regular     Regular     Promotional
[25] Promotional
Levels: Promotional Regular
mean(modelo4 == teste$Tipo.de.Cliene)
[1] 0.72
table(modelo4, teste$Tipo.de.Cliene)
             
modelo4       Promotional Regular
  Promotional          15       2
  Regular               5       3
modelo5 <- knn(train = treino[,c(2,4)],
               test = teste[,c(2,4)],
               cl = treino$Tipo.de.Cliene,
               k = 6)
modelo5
 [1] Promotional Promotional Promotional Promotional Promotional Promotional
 [7] Promotional Regular     Promotional Promotional Regular     Promotional
[13] Promotional Promotional Regular     Promotional Regular     Promotional
[19] Promotional Promotional Regular     Regular     Regular     Promotional
[25] Promotional
Levels: Promotional Regular
mean(modelo5 == teste$Tipo.de.Cliene)
[1] 0.76
table(modelo5, teste$Tipo.de.Cliene)
             
modelo5       Promotional Regular
  Promotional          16       2
  Regular               4       3
modelo6 <- knn(train = treino[,c(2,4)],
               test = teste[,c(2,4)],
               cl = treino$Tipo.de.Cliene,
               k = 7)
modelo6
 [1] Promotional Promotional Promotional Promotional Promotional Promotional
 [7] Promotional Regular     Promotional Promotional Regular     Promotional
[13] Promotional Promotional Regular     Promotional Regular     Regular    
[19] Promotional Promotional Regular     Regular     Regular     Promotional
[25] Promotional
Levels: Promotional Regular
mean(modelo6 == teste$Tipo.de.Cliene)
[1] 0.72
table(modelo6, teste$Tipo.de.Cliene)
             
modelo6       Promotional Regular
  Promotional          15       2
  Regular               5       3

Para um modelo de KNN, o que obteve melhor resultado foi o com 0,76% da taxa de acerto.

##Conclusão

Para o tipo de dados que estamos trabalhando, havaria um modelo eficiente, ou para a quantidade de dados que estamos trabalhando a arvore de decisão, se torna mais eficiente, visto que já conseguimos identificar ou traçar um tipo de perfil, modelo do tipo KNN, necessita de mais variaveis para fazer um comparativo e validações melores, não sendo ele um modelo ideal para estes dados.