El análisis de clientes a través de metodología RFM es uno de las herramientas más sencillas y eficientes de implementar sobre nuestros datos. Tiene el objetivo de segmentar una determinada cartera de clientes y situarlos en una escala de valor de acuerdo con tres variables de negocio.
Recurrencia (Recency): última operación/compra realizada por un determinado cliente: ¿Qué tan reciente fue la última compra del cliente?
Frecuencia (Frecuency): Número de operaciones/compras realizadas en un periodo de tiempo determinado por cliente. ¿Con qué frecuencia compra?
Valor (Monetary Value) : Venta valorizada de las operaciones/compras realizadas en un determinado periodo de tiempo por cliente. ¿Cuánto está dispuesto a gastar?
Como resultado de dicha categorización se pueden ordenar aquellos segmentos de mayor valor (más antigüedad, mayor frecuencia de compra e inversión, entre otras) y de menor valor. Esto nos permite realizar eficientes estrategias como: 1. Integrar con las áreas de marketing para campañas promocionales de inbound y outbound marketing. 2. Generación de protocolos de atención de clientes de forma diferencia para cada segmento. 3. Desarrollo de un lenguaje común entre las áreas comerciales y de marketing. 4. Optimizar el pareto de clientes focalizando estrategias eficientes sobre aquellos grupos más “abandonados”, entre otras. 5. Considerando que el ecommerce está tomando una fuerza importante a partir la digitalización de las ventas e información de cliente en general, este tipo de estrategias ayudan a transformar los datos en informacón valiosa para la toma de decisiones.
A continuación, les muestro una breve ejecución de un análisis RFM basado en un dataset de ejemplo.
Otras estrategias de segmentación de clientes como algoritmos agrupamiento como K-means, los mostraré en otro posteo.
Luego de la etapa de limpieza y procesamiento de datos, obtenemos el siguiente análisis descriptivo de la data:
summary(df)
skim(df)
## InvoiceNo StockCode Description Quantity
## 576339 : 542 85123A : 2035 Length:397884 Min. : 1.00
## 579196 : 533 22423 : 1723 Class :character 1st Qu.: 2.00
## 580727 : 529 85099B : 1618 Mode :character Median : 6.00
## 578270 : 442 84879 : 1408 Mean : 12.99
## 573576 : 435 47566 : 1396 3rd Qu.: 12.00
## 567656 : 421 20725 : 1317 Max. :80995.00
## (Other):394982 (Other):388387
## InvoiceDate UnitPrice CustomerID
## Min. :2010-12-01 Min. : 0.001 17841 : 7847
## 1st Qu.:2011-04-07 1st Qu.: 1.250 14911 : 5675
## Median :2011-07-31 Median : 1.950 14096 : 5111
## Mean :2011-07-10 Mean : 3.116 12748 : 4595
## 3rd Qu.:2011-10-20 3rd Qu.: 3.750 14606 : 2700
## Max. :2011-12-09 Max. :8142.750 15311 : 2379
## (Other):369577
## Country total_dolar
## United Kingdom:354321 Min. : 0.00
## Germany : 9040 1st Qu.: 4.68
## France : 8341 Median : 11.80
## EIRE : 7236 Mean : 22.40
## Spain : 2484 3rd Qu.: 19.80
## Netherlands : 2359 Max. :168469.60
## (Other) : 14103
| Name | df |
| Number of rows | 397884 |
| Number of columns | 9 |
| _______________________ | |
| Column type frequency: | |
| character | 1 |
| Date | 1 |
| factor | 4 |
| numeric | 3 |
| ________________________ | |
| Group variables | None |
Variable type: character
| skim_variable | n_missing | complete_rate | min | max | empty | n_unique | whitespace |
|---|---|---|---|---|---|---|---|
| Description | 0 | 1 | 6 | 36 | 0 | 3866 | 0 |
Variable type: Date
| skim_variable | n_missing | complete_rate | min | max | median | n_unique |
|---|---|---|---|---|---|---|
| InvoiceDate | 0 | 1 | 2010-12-01 | 2011-12-09 | 2011-07-31 | 305 |
Variable type: factor
| skim_variable | n_missing | complete_rate | ordered | n_unique | top_counts |
|---|---|---|---|---|---|
| InvoiceNo | 0 | 1 | FALSE | 18532 | 576: 542, 579: 533, 580: 529, 578: 442 |
| StockCode | 0 | 1 | FALSE | 3665 | 851: 2035, 224: 1723, 850: 1618, 848: 1408 |
| CustomerID | 0 | 1 | FALSE | 4338 | 178: 7847, 149: 5675, 140: 5111, 127: 4595 |
| Country | 0 | 1 | FALSE | 37 | Uni: 354321, Ger: 9040, Fra: 8341, EIR: 7236 |
Variable type: numeric
| skim_variable | n_missing | complete_rate | mean | sd | p0 | p25 | p50 | p75 | p100 | hist |
|---|---|---|---|---|---|---|---|---|---|---|
| Quantity | 0 | 1 | 12.99 | 179.33 | 1 | 2.00 | 6.00 | 12.00 | 80995.00 | ▇▁▁▁▁ |
| UnitPrice | 0 | 1 | 3.12 | 22.10 | 0 | 1.25 | 1.95 | 3.75 | 8142.75 | ▇▁▁▁▁ |
| total_dolar | 0 | 1 | 22.40 | 309.07 | 0 | 4.68 | 11.80 | 19.80 | 168469.60 | ▇▁▁▁▁ |
Para implementar el análisis de RFM necesitamos seguir procesando el conjunto de datos mediante los siguientes pasos:
df_RFM <- df %>%
group_by(CustomerID) %>%
summarise(recency=as.numeric(as.Date("2012-01-01")-max(InvoiceDate)),
frequenci=n_distinct(InvoiceNo), monetary= sum(total_dolar)/n_distinct(InvoiceNo))
summary(df_RFM)
## CustomerID recency frequenci monetary
## 12346 : 1 Min. : 23.0 Min. : 1.000 Min. : 3.45
## 12347 : 1 1st Qu.: 40.0 1st Qu.: 1.000 1st Qu.: 178.62
## 12348 : 1 Median : 73.0 Median : 2.000 Median : 293.90
## 12349 : 1 Mean :115.1 Mean : 4.272 Mean : 419.17
## 12350 : 1 3rd Qu.:164.8 3rd Qu.: 5.000 3rd Qu.: 430.11
## 12352 : 1 Max. :396.0 Max. :209.000 Max. :84236.25
## (Other):4332
kable(head(df_RFM))
| CustomerID | recency | frequenci | monetary |
|---|---|---|---|
| 12346 | 348 | 1 | 77183.6000 |
| 12347 | 25 | 7 | 615.7143 |
| 12348 | 98 | 4 | 449.3100 |
| 12349 | 41 | 1 | 1757.5500 |
| 12350 | 333 | 1 | 334.4000 |
| 12352 | 59 | 8 | 313.2550 |
(Recency): última operación/compra realizada por un determinado cliente: ¿Qué tan reciente fue la última compra del cliente?
hist(df_RFM$recency, breaks = 100, include.lowest = TRUE)
(Frecuency): Número de operaciones/compras realizadas en un periodo de tiempo determinado por cliente. ¿Con qué frecuencia compra?
hist(df_RFM$frequenci, breaks = 1000, include.lowest = TRUE, right = TRUE)
(Monetary Value) : Venta valorizada de las operaciones/compras realizadas en un determinado periodo de tiempo por cliente. ¿Cuánto está dispuesto a gastar?
hist(df_RFM$monetary, breaks = 100)
Para normalizar la data.
df_RFM$monetary <- log(df_RFM$monetary)
hist(df_RFM$monetary)
En este punto ordenamos la data para poder ejecutar algunos algoritmos de clusters no supervisados.
df_RFM2 <- df_RFM
row.names(df_RFM2) <- df_RFM2$CustomerID
## Warning: Setting row names on a tibble is deprecated.
df_RFM2$CustomerID <- NULL
df_RFM2 <- scale(df_RFM2)
summary(df_RFM2)
## recency frequenci monetary
## Min. :-0.9205 Min. :-0.42505 Min. :-5.8832
## 1st Qu.:-0.7505 1st Qu.:-0.42505 1st Qu.:-0.6153
## Median :-0.4205 Median :-0.29514 Median : 0.0493
## Mean : 0.0000 Mean : 0.00000 Mean : 0.0000
## 3rd Qu.: 0.4968 3rd Qu.: 0.09457 3rd Qu.: 0.5576
## Max. : 2.8091 Max. :26.59496 Max. : 7.6012
Acá vamos a ejemplificar a través de algunas técnicas de cluster como Agglomerative clustering y Divisive hierarchical clustering sin entrar mucho en detalles. En rigor, lo que queremos entender es cómo se agrupan mis clientes en relación a las variables RFM. Sin embargo, más allá de la frecuencia, recurrencia y valor, podemos implementarestos algoritmos con más variables para obtener clusters más interesantes de estudiar.
d <- dist(df_RFM2, method = "euclidean")
# Hierarchical clustering con la función "Complete"
hc1 <- hclust(d, method = "complete" )
# Para graficar a través de Dendrograma
plot(hc1, cex = 0.6, hang = -1)
Acá podemos ver un dendrograma a través de la función de agrupación ward.D2 y definir una K de grupos para entender las divisiones de los mismos.
hc3 <- hclust(d, method = "ward.D2")
## Para visualizar los grupos generados
sub_cluster <- cutree(hc3, k = 5)
table(sub_cluster)
## Graficamos en un dendrograma
plot(hc3, cex = 0.6, xlab = "Customer ID")
rect.hclust(hc3, k = 5, border = 2:5)
## sub_cluster
## 1 2 3 4 5
## 2133 772 1092 319 22
Asimismo, podemos utilizar una función específica para ver dichos resultados en un gráfico de dispersión y que visualmente puede ser más interesante.
fviz_cluster(list(data = df_RFM2, cluster = sub_cluster))
El objetivo es ejecutar un algoritmo que nos permita obtener una recomendación de la cantidad de grupos óptimos de acuerdo al comportamiento de nuestras variabes y para eso utilizamos las siguientes funciones
fviz_nbclust(df_RFM2, FUN = hcut, method = "wss")
fviz_nbclust(df_RFM2, FUN = hcut, method = "silhouette")
gap_stat <- clusGap(df_RFM2, FUN = hcut, nstart = 25, K.max = 10, B = 10)
fviz_gap_stat(gap_stat)
Podemos observar que a partir de los óptimos recomendados por los algoritmos, tomé en consideración una agrupación de 3 clusters. Sin embargo, se debe tener muy presente para este tipo de desarrollos las medidas de disimilitud o donde cortar el dendrograma, entre otros.
Finalmente la tabla nos muestra los datos agrupados en 3 clusters y la media de cada una de las variables asociadas a RFM Es decir, se realiza calificación basada en la categorización de los datos definidos en el proceso, entregando un perfil definido de cada cliente para luego poder realizar acciones de marketing específicas que mejoren la performance de nuestro negocio.
clusters <- cutree(hc3,k = 3)
clusters[1:3]
table(clusters)
aggregate(df_RFM[,2:4], by=list(clusters), mean)
## 12346 12347 12348
## 1 1 1
## clusters
## 1 2 3
## 3544 772 22
## Group.1 recency frequenci monetary
## 1 1 76.69498 4.444131 5.711284
## 2 2 293.65674 1.396373 5.320760
## 3 3 28.09091 77.454545 6.601579
https://www.Kaggle.com https://www.r-bloggers.com/2019/07/customer-segmentation-using-rfm-analysis/ https://www.unica360.com/analisis-rfm-en-retail-empezando-a-segmentar-clientes-i https://www.business-science.io/business/2016/08/07/CustomerSegmentationPt1.html https://uc-r.github.io/hc_clustering