Sobre:

Este projeto, tem como objetivo realizar a segmentação de clientes de um food delivery.

Serão utilizadas técnicas avançadas de analytics, modelagem estatística e machine learning.

Através do processo realizado com as principais técnicas de data science, devemos ser capazes de identificar com exatidão o perfil mercadológico da empresa de food delivery assim como o perfil de seus clientes. Dentre os objetivos deste projeto estão:

Librarys:

Carrega pacotes que utilizaremos no projeto.

pacman::p_load(tidyverse,knitr,caret,caTools,plyr,data.table,psych,vcd,factoextra,GGally,lubridate,mosaic, sjmisc,stringi,cluster,NbClust,clValid,clustertend,fpc,ggcorrplot,pracma)

Dataset:

Carrega o dataset na memória.

df <- read_csv("dataset.csv")
## Parsed with column specification:
## cols(
##   id_transacao = col_character(),
##   horario_pedido = col_datetime(format = ""),
##   localidade = col_double(),
##   nome_item = col_character(),
##   quantidade_item = col_double(),
##   latitude = col_double(),
##   longitude = col_double()
## )

Dicionário de dados:

dicionario <- tibble(VARIAVEL = c('id_trancacao','horario_pedido','localidade','nome_item','quantidade_item','latitude','longitude'),
                     DESCRICAO = c('ID da transação do pedido. Um mesmo ID pode ter vários itens de um pedido.', 'Horário em que o pedido foi realizado na plataforma.','Localidade que processou o pedido (unidade do restaurante).','Nome do item do pedido.','Quantidade de itens do pedido.','Latitude da localidade onde o pedido foi gerado.','Longitude da localidade onde o pedido foi gerado.'));kable(dicionario)
VARIAVEL DESCRICAO
id_trancacao ID da transação do pedido. Um mesmo ID pode ter vários itens de um pedido.
horario_pedido Horário em que o pedido foi realizado na plataforma.
localidade Localidade que processou o pedido (unidade do restaurante).
nome_item Nome do item do pedido.
quantidade_item Quantidade de itens do pedido.
latitude Latitude da localidade onde o pedido foi gerado.
longitude Longitude da localidade onde o pedido foi gerado.

Análise exploratória:

Tipos de dados e variáveis:

str(df)
## tibble [260,645 × 7] (S3: spec_tbl_df/tbl_df/tbl/data.frame)
##  $ id_transacao   : chr [1:260645] "0x7901ee" "0x7901ee" "0x7901ee" "0x12b47f" ...
##  $ horario_pedido : POSIXct[1:260645], format: "2019-01-16 18:33:00" "2019-01-16 18:33:00" ...
##  $ localidade     : num [1:260645] 7 7 7 3 3 6 6 2 2 2 ...
##  $ nome_item      : chr [1:260645] "bebida" "pizza" "sobremesa" "salada" ...
##  $ quantidade_item: num [1:260645] 2 2 2 1 1 2 2 2 2 2 ...
##  $ latitude       : num [1:260645] 41.8 41.8 41.8 41.9 41.9 ...
##  $ longitude      : num [1:260645] -88 -88 -88 -87.6 -87.6 ...
##  - attr(*, "spec")=
##   .. cols(
##   ..   id_transacao = col_character(),
##   ..   horario_pedido = col_datetime(format = ""),
##   ..   localidade = col_double(),
##   ..   nome_item = col_character(),
##   ..   quantidade_item = col_double(),
##   ..   latitude = col_double(),
##   ..   longitude = col_double()
##   .. )

Há 260.645 instâncias e 7 variáveis no dataset.

Estatísticas básicas:

df %>% ggplot(aes(x=nome_item,y=quantidade_item))+
  geom_boxplot(aes(fill=nome_item))+
  theme_minimal()+
  ggtitle("Boxplot por item vendido")

Todos os itens são vendidos entre as quantidades 1 a 5, é interessante ver aqui que Bebida possui mediana concentrada em 3, enquanto as demais estão na faixa de 2 quantidades.

Salada possui intervalo interquartil menor, isso significa dizer que sem a presença dos outliers (valores extremos à media) salada varia entre 1 e 2 itens pedidos.

A média também é maior que a mediana em todas as amostras, pois o “bigode” possui inclinação para a parte superior, isso é um indicativo que as amostras são assimétricas.

Instâncias únicas:

as.data.frame(map(df,uniqueN)) %>% gather(variavel,valor,1:7)
##          variavel  valor
## 1    id_transacao 100000
## 2  horario_pedido  76799
## 3      localidade      9
## 4       nome_item      4
## 5 quantidade_item      5
## 6        latitude      9
## 7       longitude      9

Tabela Pivot:

Construção de uma tabela pivot com agrupamento por id de transação e criação da variável de total de pedidos:

df1 <- df %>% 
  group_by(id_transacao) %>% 
  spread(nome_item,quantidade_item) %>% 
  tidyr::replace_na(list(bebida = 0,
                  pizza = 0,
                  salada = 0,
                  sobremesa = 0)) %>% 
  mutate(total_pedidos = bebida+pizza+salada+sobremesa);kable(head(df1))
id_transacao horario_pedido localidade latitude longitude bebida pizza salada sobremesa total_pedidos
0x7901ee 2019-01-16 18:33:00 7 41.79413 -88.01014 2 2 0 2 6
0x12b47f 2019-09-04 12:36:00 3 41.88449 -87.62706 0 0 1 1 2
0x6d6979 2019-03-18 00:27:00 6 41.78458 -87.60756 0 2 0 2 4
0x78dd1e 2019-09-22 00:10:00 2 42.04931 -87.67761 2 2 0 2 6
0x4df8ab 2019-01-17 11:35:00 8 41.89420 -87.62096 0 0 3 3 6
0x3be6d3 2019-12-21 01:05:00 6 41.78458 -87.60756 0 1 0 1 2

Série Temporal - Pedidos realizados por mês:

df %>% mutate(mes = month(horario_pedido)) %>%
  ggplot(aes(mes))+
  geom_freqpoly(binwidth = 1)+
  theme_minimal()+
  ylim(c(19900,23000))+
  scale_x_continuous(breaks=1:12)+
  ggtitle("Pedidos realizados por mês")
## Warning: Removed 2 row(s) containing missing values (geom_path).

Fevereiro é o mês em que foram realizados o menor número de pedidos em comparação aos demais meses.

Vamos investigar mais a fundo e analisar os piores dias deste mês.

Também é possível identifcar que maio e janeiro foram os melhores meses do ano em pedidos realizados.

p <- function(x){
df %>% mutate(mes = month(horario_pedido),
              dia = day(horario_pedido),
              ano = year(horario_pedido)) %>%
  filter(mes == x, ano == 2019) %>%
  ggplot(aes(x=dia)) + 
  geom_freqpoly(binwidth = 1)+
  ylim(c(500,1000))+
  scale_x_continuous(breaks = 1:31)+
  ggtitle(sprintf("Mês %d",x))+
  theme_minimal()
}
gridExtra::grid.arrange(p(2),ncol=1,nrow=1,
            top=textGrob("Pedidos realizados - 2019", gp=gpar(fontsize=16,font=2)))
## Warning: Removed 2 row(s) containing missing values (geom_path).

Aqui é possível ver que há quedas grandes no número de pedidos, especialmente nos dias 5, 22 e 24.

Embora fevereiro tenha sido o pior mês em número de pedidos, vamos analisar os demais meses afim de identifcar se esse padrão se repete.

df %>% mutate(dia = day(horario_pedido),
              mes = month(horario_pedido),
              ano = year(horario_pedido)) %>% 
  ggplot(aes(dia))+
  geom_freqpoly(binwidth=1)+
  ylim(c(7500,10000))+
  scale_x_continuous(breaks = 1:30)+
  theme_minimal()+
  ggtitle("Pedidos realizados por dia do mês - análise do ano inteiro")
## Warning: Removed 3 row(s) containing missing values (geom_path).

Na visão consolidada de todos os meses, é possível ver que entre os dias 28 a 30, o número de pedidos cai (vamos desconsiderar o dia 31, visto que não são todos os meses do ano que possuem esse dia no calendário).

gridExtra::grid.arrange(p(1),p(2),p(3),p(4),p(5),p(6),
                        p(7),p(8),p(9),p(10),p(11),p(12),
                        ncol=3,nrow=4,
                        top=textGrob("Pedidos realizados - 2019", gp=gpar(fontsize=16,font=2)))
## Warning: Removed 2 row(s) containing missing values (geom_path).

## Warning: Removed 2 row(s) containing missing values (geom_path).

## Warning: Removed 2 row(s) containing missing values (geom_path).

## Warning: Removed 2 row(s) containing missing values (geom_path).

## Warning: Removed 2 row(s) containing missing values (geom_path).

## Warning: Removed 2 row(s) containing missing values (geom_path).

## Warning: Removed 2 row(s) containing missing values (geom_path).

## Warning: Removed 2 row(s) containing missing values (geom_path).

## Warning: Removed 2 row(s) containing missing values (geom_path).

## Warning: Removed 2 row(s) containing missing values (geom_path).

## Warning: Removed 2 row(s) containing missing values (geom_path).

## Warning: Removed 2 row(s) containing missing values (geom_path).

Analisando todos os meses por dia do mês, não pode-se afirmar que há um padrão quanto as quedas e picos de vendas e isso varia conforme o mês.

Série Tempora - Pedidos realizados por dia da semana:

df2 <- df %>% 
  mutate(ano = year(horario_pedido),
         mes = month(horario_pedido),
         dia_mes = day(horario_pedido),
         dia_semana = weekdays(horario_pedido),
         horas = hour(horario_pedido)) %>% 
  mutate(dia_semana = factor(dia_semana, levels = c("segunda","terça","quarta",
                                                    "quinta","sexta","sábado","domingo"),
                             labels = c("segunda","terça","quarta","quinta","sexta",
                                        "sábado","domingo")))
p_dia_semana <- function(month,color){
  df2 %>% 
    filter(ano == 2019, mes == month) %>% 
    group_by(dia_semana) %>% 
    dplyr::summarise(n = n()) %>% 
    ggplot(aes(x=dia_semana,y=n))+
    geom_col(size =1, fill = color)+
    theme_minimal()+
    ggtitle(sprintf("Mês %d", month))+
    xlab("")+
    geom_text(aes(label=round(n/sum(n),2)),vjust=1.6,color="black",size=3.5)
}

gridExtra::grid.arrange(p_dia_semana(1,"lightblue"),
                        p_dia_semana(2,"lightblue"),
                        p_dia_semana(3,"lightblue"),
                        p_dia_semana(4,"palegreen3"),
                        p_dia_semana(5,"palegreen3"),
                        p_dia_semana(6,"palegreen3"),
                        p_dia_semana(7,"coral1"),
                        p_dia_semana(8,"coral1"),
                        p_dia_semana(9,"coral1"),
                        p_dia_semana(10,"grey"),
                        p_dia_semana(11,"grey"),
                        p_dia_semana(12,"grey"),
                        ncol=3,nrow=4,
                        top=textGrob("Pedidos realizados por dia da semana - 2019
                                     ",
                                     gp=gpar(fontsize=16,font=2)))
## `summarise()` ungrouping output (override with `.groups` argument)
## `summarise()` ungrouping output (override with `.groups` argument)
## `summarise()` ungrouping output (override with `.groups` argument)
## `summarise()` ungrouping output (override with `.groups` argument)
## `summarise()` ungrouping output (override with `.groups` argument)
## `summarise()` ungrouping output (override with `.groups` argument)
## `summarise()` ungrouping output (override with `.groups` argument)
## `summarise()` ungrouping output (override with `.groups` argument)
## `summarise()` ungrouping output (override with `.groups` argument)
## `summarise()` ungrouping output (override with `.groups` argument)
## `summarise()` ungrouping output (override with `.groups` argument)
## `summarise()` ungrouping output (override with `.groups` argument)

Não há anomalias considerando total de pedidos por dia da semana. E embora em geral o fim de semana, se apresente mais performático para alguns meses, a diferença entre os dias em número de pedidos **não é ** determinante.

df %>% mutate(dia = day(horario_pedido),
              mes = month(horario_pedido),
              ano = year(horario_pedido),
              hora = hour(horario_pedido)) %>% 
  ggplot(aes(hora))+
  geom_freqpoly(binwidth = 1)+
  scale_x_continuous(breaks = 0:23)+
  theme_minimal()+
  ggtitle("Pedidos realizados por hora")

Entre 2 e 10 da manhã não há pedidos;

A faixa da meia-noite é onde mais são realizados os pedidos;

No período da tarde a faixa entre 14 e 16h horas é onde se tem menos pedidos;

A noite, em especial a faixa entre 20 a 22 horas também há uma queda no numero de pedidos.

Itens mais vendidos:

df2 %>% group_by(nome_item) %>% dplyr::summarise(n = n()) %>% 
  ggplot(aes(x=nome_item,y=n)) +
  geom_col(fill = "lightblue")+
  theme_minimal()+
  geom_text(aes(label=round(n/sum(n),2)),vjust=1.6,color="black",size=3.5)+
  labs(title = "Itens mais vendidos", x="")
## `summarise()` ungrouping output (override with `.groups` argument)

Sobremesas vendem mais que pizza, enquanto bebidas vendem quase mesma proporção que saladas.

Frequência de pedidos realizados:

df2 %>% select(nome_item,quantidade_item)%>% 
  ggplot(aes(x=quantidade_item, fill = nome_item))+
  geom_histogram(aes(y=..density..),bins = 5)+
  facet_grid(~nome_item)+
  labs(title="Frequência de quantidade de itens por pedido realizado",x="quantidade")

Este plot reforça nosso pensamento anterior, sobremesas possuem uma distribuiçao mais uniforme em comparação os demais itens, assim como bebida também possui maior frequência de pedidos nas faixas superiores a 2 quantidades.

É interessante ver também que, predominantemente, quando se pede salada, em ≃47% das vezes se pede apenas 1 quantidade.

Pedidos por Localidade:

df2 %>% group_by(localidade) %>% dplyr::summarise(n=n()) %>% 
  ggplot(aes(x=reorder(localidade,n),y=n))+
  geom_col(fill="lightblue")+
  coord_flip()+
  theme_minimal()+
  labs(x="Localidade",title="Pedidos por localidade")+
  geom_text(aes(label=round(n/sum(n),3)),vjust=0.5,color="black",size=3.5, hjust=1.5)
## `summarise()` ungrouping output (override with `.groups` argument)

A pior localidade é a de numero 5. Poderíamos estender a análise e tentar entender o motivo pelo qual essa localidade tem performance inferior às demais, analisando itens vendidos por pedido realizado e assim ir aprofundando a análise. Contudo, focaremos na clusterização para então segmentar os clientes em grupos.

Correlação entre variáveis numéricas:

df3 <- df1 %>% select(bebida,pizza,salada,sobremesa);df3 <- as.data.frame(df3)
## Adding missing grouping variables: `id_transacao`
df3$id_transacao <- NULL;df3 <- as_tibble(df3);ggpairs(df3)

Analisando a correlação entre as variáveis, há alguns insights interessantes que podemos tirar daqui:

Pizza e Bebida possuem forte correlação positiva, ou seja, a medida que se pedem mais pizzas, também se pedem mais bebidas.

Salada, possui relacionamento moderadomente negativo com pizza, ou seja, há uma tendência de que quanto mais se pede salada, menos se pedem pizzas.

Clusterização:

Ajuste do dataset para clusterização:

df4 <- df1 %>% 
  select(bebida,pizza,sobremesa,salada,localidade);df4
## Adding missing grouping variables: `id_transacao`
## # A tibble: 100,000 x 6
## # Groups:   id_transacao [100,000]
##    id_transacao bebida pizza sobremesa salada localidade
##    <chr>         <dbl> <dbl>     <dbl>  <dbl>      <dbl>
##  1 0x7901ee          2     2         2      0          7
##  2 0x12b47f          0     0         1      1          3
##  3 0x6d6979          0     2         2      0          6
##  4 0x78dd1e          2     2         2      0          2
##  5 0x4df8ab          0     0         3      3          8
##  6 0x3be6d3          0     1         1      0          6
##  7 0x755a0b          3     3         4      1          7
##  8 0x653685          1     4         4      0          6
##  9 0x44fe1b          1     2         2      0          2
## 10 0x8ade21          2     2         3      1          7
## # … with 99,990 more rows
df4 <- as.data.frame(df4);df4$id_transacao <- NULL;df4 <- as_tibble(df4)

Dados Amostrais:

Seleção de 2% dos dados de forma aleatória para a execução do algoritimo Hopkins e definição do valor de K.

set.seed(123)
df_sample <- df4 %>% as_tibble() %>% 
  mutate_if(is.numeric,scale) %>% 
  sample_frac(0.02)

Dados para Clusterização:

df_final <- df4 %>% 
  mutate_if(is.numeric,scale)

Avaliando a tendência do clustering:

Estatística Hopkins para o conjunto de dados:

  • Valores >.5 significam que o dataset não é "clusterizável;

  • Valores <.5 significam que o dataset é “clusterizável”;

  • Quanto mais próximo de zero, melhor.

hopkins(df_sample,n=nrow(df_sample)-1) 
## $H
## [1] 0.2051347

O dataset é “clusterizável”.

Definição do número de clusters:

set.seed(123)
clusters <- NbClust(df_sample,
                     distance="euclidean",
                     min.nc=2,
                     max.nc=15,
                     method="kmeans",
                     index="all")

## *** : The Hubert index is a graphical method of determining the number of clusters.
##                 In the plot of Hubert index, we seek a significant knee that corresponds to a 
##                 significant increase of the value of the measure i.e the significant peak in Hubert
##                 index second differences plot. 
## 

## *** : The D index is a graphical method of determining the number of clusters. 
##                 In the plot of D index, we seek a significant knee (the significant peak in Dindex
##                 second differences plot) that corresponds to a significant increase of the value of
##                 the measure. 
##  
## ******************************************************************* 
## * Among all indices:                                                
## * 8 proposed 2 as the best number of clusters 
## * 10 proposed 3 as the best number of clusters 
## * 2 proposed 10 as the best number of clusters 
## * 1 proposed 13 as the best number of clusters 
## * 1 proposed 14 as the best number of clusters 
## * 1 proposed 15 as the best number of clusters 
## 
##                    ***** Conclusion *****                            
##  
## * According to the majority rule, the best number of clusters is  3 
##  
##  
## *******************************************************************

O algoritmo NbClust recomendou a utilização de 3 clusters para a construção do modelo.

Modelo:

set.seed(123)
modelo <- kmeans(df_final,3);df1$cluster <- modelo$cluster

Plot do Modelo:

cluster_viz <- eclust(df_sample,"kmeans",k=3,nstart=25,graph=FALSE)
fviz_cluster(cluster_viz,geom="point")

Cluster plot nos mostra como ficaram os agrupamentos de dados a partir da aplicação do modelo de Machine Learning.

Há pouca ou nenhuma sobreposição nos clusters. Isso quer dizer a clusterização foi feita de forma eficiente e os agrupamentos possuem distinção entre si.

Análise exploratória por Cluster:

Pedidos por Cluster:

options(scipen = 999) 
df1 %>% as.data.frame() %>% 
  select(bebida,pizza,salada,sobremesa,cluster) %>% 
  as_tibble() %>% 
  gather(item,qtd,1:4) %>% 
  mutate(cluster = factor(cluster, levels = c(1,2,3),
                          labels = c("Grupo 1","Grupo 2","Grupo 3"))) %>% 
  group_by(cluster) %>% 
  dplyr::summarise(qtd = sum(qtd)) %>% 
  ggplot(aes(x=cluster,y=qtd))+
  geom_col(aes(fill = cluster))+
  theme_minimal()+
  ggtitle("Pedidos realizados por Grupo de clientes")+
  geom_text(aes(label=round(qtd/sum(qtd),2)),vjust=1.6,color="white",size=3.5)
## `summarise()` ungrouping output (override with `.groups` argument)

Em número de pedidos, o cluster número 2 é visivelmente mais performático que o cluster 1 e 3, tendo 56% de todos os pedidos realizados.

Itens mais vendidos:

itens_mais_vendidos <- function(x,cor_escolhida){
  df1 %>% as.data.frame() %>% 
    filter(cluster == x) %>% 
    select(bebida,pizza,salada,sobremesa) %>% 
    as_tibble() %>% 
    gather(item,qtd,1:4) %>% 
    group_by(item) %>% 
    dplyr::summarise(qtd = sum(qtd)) %>% 
    ggplot(aes(x=item, y=qtd))+
    geom_col(fill = cor_escolhida)+
    ylim(c(0,150000))+
    theme_light()+
    ggtitle(sprintf("Grupo %d",x))+
    geom_text(aes(label=round(qtd/sum(qtd),2)),vjust=-1,color="black",size=3.5)
}


gridExtra::grid.arrange(itens_mais_vendidos(1,"coral2"),
                        itens_mais_vendidos(2,"skyblue3"),
                        itens_mais_vendidos(3,"palegreen3"), ncol=3,
                        top=textGrob("Itens mais vendidos por grupo
                                     ",
                                     gp=gpar(fontsize=16,font=2)))
## `summarise()` ungrouping output (override with `.groups` argument)
## `summarise()` ungrouping output (override with `.groups` argument)
## `summarise()` ungrouping output (override with `.groups` argument)

Todos os grupos tem a sobremesa como o item mais pedido.

O grupo 3 é bem interessante. Aqui os pedidos de pizza representam apenas 5% e os de bebida 2%, enquanto salada represesenta 44% de todos os pedidos realizados nesse grupo. Ou seja, podemos inferir através dessa análise que esse grupo compõe um público mais vegano se comparado aos demais.

No grupo 2 a proporção de pedidos de salada é praticamente nula, e bebida e pizza possuem grande número de pedidos.

No grupo 1, é importante notar que, embora 36 % dos pedidos sejam de pizza, apenas 11% são de bebidas. Ou seja, a venda de bebidas não necessariamente está atrelada à venda de pizzas.

Distribuição de frequência por grupos:

distplot <- function(x){
  df1 %>% as.data.frame() %>% 
  filter(cluster == x) %>% 
  select(bebida,pizza,salada,sobremesa) %>% 
  as_tibble() %>% 
  gather(item,qtd,1:4) %>% 
  filter(qtd >0) %>% 
  ggplot(aes(x=qtd,fill = item))+
  geom_histogram(aes(y=..density..),binwidth = 1,show.legend = FALSE)+
  facet_grid(~item)+
  ggtitle(sprintf("Grupo %d",x))
}

gridExtra::grid.arrange(distplot(1),
                        distplot(2),
                        distplot(3),nrow=3,ncol=1)

Grupo 1

O cluster 1, possui algumas características interessantes:

Nenhum item é vendido na faixa de 5 quantidades;

75% das vezes que se pedem bebidas pedem em 1 quantidade;

Pizza são pedidas predominantemente em 1 quantidade ou 2.

Pizza e sobremesa possuem “praticamente” o mesmo tipo de distribuição de frequência, o que podemos inferir que a compra de um item possa estar atrelado ao outro.

Grupo 2:

≃90% das vezes em que se pede salada, a quantidade escolhida é de apenas 1;

Sobremesa e pizza possuem uma distribuição bastante interessante nesse grupo:

Pizza possui maior frequência de pedidos entre as faixa de 3 a 5, e nenhum pedido na faixa com 1 item.

Sobremesa possui frequência mais concetrada na faixa de 3 a 5 e nenhum pedido na faixa de 1 a 2.

Bebidas quando pedidas, são mais frequentes na faixa entre 3 e 4.

Diante das distibuições de frequência podemos inferir que, neste grupo está inserido um tipo de público mais “corporativo” em que se compra itens em maiores quantidades, pouca ou nenhuma salada, e quando pedida a quantidade não ultrapassa a faixa de 1 item.

Grupo 3:

No grupo 3, vemos que se pedem pizza e bebidas basicamente na mesma predominância e proporção, principalmente na faixa de 1 quantidade.

Salada quando é pedida, nunca é pedida apenas 1 quantidade, e possui predominância nas faixas entre 2 e 3. Vale lembrar que, neste grupo, está o público que mais pede salada.

Sobremesa, segue a mesma tendência da salada, há predominância de pedidos realizados entre as faixas 2 e 3.

Sobremesa e salada também possuem frequência moderada entre as faixas 4 e 5 itens.

Devido as características dos 3 grupos, os classificaremos em 3 nomes:

  • Grupo 1: Regular

  • Grupo 2: Corporate

  • Grupo 3: Vegan

Pedidos por Horário:

pedidos_hora <- function(x,y){
df1 %>% as.data.frame() %>% 
  select(horario_pedido,bebida,pizza,salada,sobremesa,cluster) %>% 
  gather(item, qtd,2:5) %>% 
  mutate(horario = hour(horario_pedido),
         Grupo = factor(cluster,levels = c(1,2,3),
                        labels = c("Regular","Corporate","Vegan"))) %>% 
  select(Grupo,qtd,horario) %>% 
  filter(Grupo == x,qtd >0) %>% 
  ggplot(aes(x=horario))+
  geom_freqpoly(binwidth=1, color = y,size = 1)+
  xlim(c(0,23))+
  theme_minimal()+
  ggtitle(sprintf("Grupo %s",x))+
  xlab("Hora do dia")
}
gridExtra::grid.arrange(pedidos_hora("Regular","coral2"),
                        pedidos_hora("Corporate","steelblue"),
                        pedidos_hora("Vegan","palegreen3"),
                        nrow=3,top=textGrob("Pedidos realizados por hora
                                            ",
                                     gp=gpar(fontsize=16,font=2)))
## Warning: Removed 2 row(s) containing missing values (geom_path).

## Warning: Removed 2 row(s) containing missing values (geom_path).

## Warning: Removed 2 row(s) containing missing values (geom_path).

Aqui temos picos de pedidos bem distintos entre os grupos.

O grupo Vegan tem em sua maioria pedidos realizados no horário do almoço, enquanto o grupo Corporate tem o pico mais concentrado no fim de tarde e inicio da noite, mas também há pedidos na faixa da meia-noite.

Já o grupo regular tem pedidos em praticamente todas as faixas e seu pico está mais concentrado em horários próximo a meia-noite.

Pedidos por produto:

pedidos_hora_produtos <- function(x){
df1 %>% as.data.frame() %>% 
  select(horario_pedido,bebida,pizza,salada,sobremesa,cluster) %>% 
  gather(item, qtd,2:5) %>% 
  mutate(horario = hour(horario_pedido),
         Grupo = factor(cluster,levels = c(1,2,3),
                        labels = c("Regular","Corporate","Vegan"))) %>% 
  select(Grupo,item,qtd,horario) %>% 
  filter(Grupo == x,qtd >0) %>% 
  select(item,qtd,horario) %>% 
  as_tibble() %>% 
  ggplot(aes(x=horario, color = item))+
  geom_freqpoly(binwidth=1,size = 1)+
  xlim(c(0,23))+
  theme_minimal()+
  xlab("Hora do dia")+
  ggtitle(sprintf("Grupo %s",x))
}

gridExtra::grid.arrange(pedidos_hora_produtos("Regular"),
                        pedidos_hora_produtos("Corporate"),
                        pedidos_hora_produtos("Vegan"),
                        nrow = 3,
                        top=textGrob("Pedidos realizados por hora
                                            ",
                                     gp=gpar(fontsize=16,font=2)))
## Warning: Removed 8 row(s) containing missing values (geom_path).

## Warning: Removed 8 row(s) containing missing values (geom_path).

## Warning: Removed 8 row(s) containing missing values (geom_path).

Grupo Regular:

Um ponto interessante em relação a este grupo, é o pico de sobremesas vendidas na faixa da meia-noite.

Também é possível notar que na faixa da meia noite a venda de bebidas e pizzas estão intensamente atreladas mas isso não se repete no horário do almoço.

Grupo Corporate:

Pedidos de sobremesa, pizza e bebida estão intensamente atreladas.

Grupo Vegan:

É interessante ver aqui que, no grupo Vegan, a venda de Sobremesa acompanha a venda de saladas, e curiosamente, no horário do almoço, se pedem mais pizzas do que até mesmo bebidas.

Conclusão da Análise:

itens_mais_vendidos <- function(x,cor_escolhida){
  df1 %>% as.data.frame() %>% 
    mutate(Grupo = factor(cluster, levels = c(1,2,3),
                          labels = c("Regular","Corporate","Vegan"))) %>% 
    filter(Grupo == x) %>% 
    select(bebida,pizza,salada,sobremesa) %>% 
    as_tibble() %>% 
    gather(item,qtd,1:4) %>% 
    group_by(item) %>% 
    dplyr::summarise(qtd = sum(qtd)) %>% 
    ggplot(aes(x=item, y=qtd))+
    geom_col(fill = cor_escolhida)+
    ylim(c(0,150000))+
    theme_light()+
    ggtitle("Itens mais vendidos")+
    geom_text(aes(label=round(qtd/sum(qtd),2)),vjust=-1,color="black",size=3.5)
}

distplot <- function(x,y){
  df1 %>% as.data.frame() %>% 
    mutate(Grupo = factor(cluster, levels = c(1,2,3),
                          labels = c("Regular","Corporate","Vegan"))) %>% 
    filter(Grupo == x) %>% 
    select(bebida,pizza,salada,sobremesa) %>% 
    as_tibble() %>% 
    gather(item,qtd,1:4) %>% 
    filter(qtd >0) %>% 
    ggplot(aes(x=qtd))+
    geom_histogram(aes(y=..density..),binwidth = 1,show.legend = FALSE,fill = y)+
    facet_grid(~item)+
    ggtitle("Distribuição de Frequência")+
    xlab("Quantidade")
}

pedidos_hora_produtos <- function(x){
  df1 %>% as.data.frame() %>% 
    select(horario_pedido,bebida,pizza,salada,sobremesa,cluster) %>% 
    gather(item, qtd,2:5) %>% 
    mutate(horario = hour(horario_pedido),
           Grupo = factor(cluster,levels = c(1,2,3),
                          labels = c("Regular","Corporate","Vegan"))) %>% 
    select(Grupo,item,qtd,horario) %>% 
    filter(Grupo == x,qtd >0) %>% 
    select(item,qtd,horario) %>% 
    as_tibble() %>% 
    ggplot(aes(x=horario, color = item))+
    geom_freqpoly(binwidth=1,size = 1)+
    xlim(c(0,23))+
    theme_minimal()+
    xlab("Hora do dia")+
    ggtitle("Pedidos por hora")
}

Regular:

gridExtra::grid.arrange(itens_mais_vendidos("Regular","coral2"),
                        distplot("Regular","coral2"),
                        pedidos_hora_produtos("Regular"),
                        nrow = 3,
                        top=textGrob("Grupo Regular", gp=gpar(fontsize=16,font=2)))
## `summarise()` ungrouping output (override with `.groups` argument)
## Warning: Removed 8 row(s) containing missing values (geom_path).

Características do grupo:

  • Pedidos feitos predomintantemente em baixa quantidade de itens;

  • Sobremesa é o item mais vendidos, com picos de vendas por volta do fim da noite e no horário do almoço;

  • Bebidas não vendem tão bem quanto pizza.

Sugestão ao departamento de MKT:

  • Promocionais de pizza + bebida para alavancagem das vendas de bebidas;

  • Aumentar o mix de bebidas disponíveis ao consumidor final;

  • Combos promocionais de grandes quantidades para alavancar vendas nessa faixa;

Corporate:

gridExtra::grid.arrange(itens_mais_vendidos("Corporate","skyblue4"),
                        distplot("Corporate","skyblue4"),
                        pedidos_hora_produtos("Corporate"),
                        nrow = 3,
                        top=textGrob("Grupo Corporate", gp=gpar(fontsize=16,font=2)))
## `summarise()` ungrouping output (override with `.groups` argument)
## Warning: Removed 8 row(s) containing missing values (geom_path).

Características do grupo:

  • Em sua maioria pedidos realizados em grandes quantidades;

  • Venda quase nula de saladas;

  • Bebidas, pizzas e sobremesas possuem praticamente a mesma proporçao de vendas;

  • Picos de vendas estão essencialmente na faixa do fim de tarte para o inicio da noite, embora também hajam pedidos na faixa da meia-noite.

Sugestão para o departamento de MKT:

  • Promocionais de combos para empresas para impulsionamento de vendas para esse público.

Vegan:

gridExtra::grid.arrange(itens_mais_vendidos("Vegan","palegreen3"),
                        distplot("Vegan","palegreen3"),
                        pedidos_hora_produtos("Vegan"),
                        nrow = 3,
                        top=textGrob("Grupo Vegan", gp=gpar(fontsize=16,font=2)))
## `summarise()` ungrouping output (override with `.groups` argument)
## Warning: Removed 8 row(s) containing missing values (geom_path).

Características do grupo:

  • Pedidos são realizados essencialmente na hora do almoço;

  • Venda de pizzas e bebidas somam apenas 7% do total das vendas;

  • Salada e sobremesa quando pedidas, nunca são pedidas na faixa de 1 unidade.

Sugestão para o departamento de MKT:

  • Incluir no mix de produtos a opção de pizza vegana;

  • Incluir mais opções de bebidas, principalmente voltadas para o público vegano (chás, mates e etc);

  • Promocionais em outros horários que não sejam horário de almoço