Agrupación de clientes basada en proximidad espacial

Proporcionar un ejemplo de codificación sobre cómo realizar la agrupación de clientes de proximidad espacial, aplicable p. cuando se buscan múltiples centros de gravedad (es decir, cuando se desea ubicar varios almacenes). La lógica y el enfoque son los mismos que en cualquier tipo de problema de agrupamiento basado en la distancia.

Aplicaré la agrupación en clústeres de k-medias para agrupar clientes en función de su distancia espacial.

El algoritmo para la agrupación de k-medias está bien explicado, p. Ej. por este artículo: https://www.datanovia.com/en/lessons/k-means-clustering-in-r-algorith-and-practical-examples/

Primero defino un marco de datos que contiene coordenadas de latitud y longitud aleatorias, que representan clientes distribuidos al azar.

customer_df <- as.data.frame(matrix(nrow=1000,ncol=2))
colnames(customer_df) <- c("lat","long")
customer_df$lat <- runif(n=1000,min=-90,max=90)
customer_df$long <- runif(n=1000,min=-180,max=180)

Aquí ves el encabezado del marco de datos:

head(customer_df)
##         lat        long
## 1 -42.69660   58.067160
## 2  37.31715  179.655272
## 3 -28.68660   -3.025719
## 4 -76.15463  117.119388
## 5 -14.84898 -162.408406
## 6  54.19468 -128.476143

El algoritmo de agrupación de k-medias estándar selecciona k puntos iniciales aleatorios y los define como los centros de agrupación. Luego, el algoritmo asigna puntos de datos a cada centro de grupo, basándose en una distancia mínima.

En este caso, queremos utilizar más adelante el algoritmo de agrupación en clústeres para resolver problemas de ubicación de instalaciones, considerando varios almacenes para ubicar. Por tanto, me parece más apropiado seleccionar centros de conglomerados que estén razonablemente distanciados entre sí. Para esto, defino una función que elige el número definido de centros de inicio en función de la dimensión de longitud del conjunto de datos espaciales:

initial_centers <- function(customers,centers){
  quantiles <- c()
  for(i in 1:centers){
    quantiles <- c(quantiles,i*as.integer(nrow(customers)/centers))
  }
  quantiles
}

Ahora podemos aplicar la función anterior, en combinación con la función kmeans del paquete base R. En este ejemplo, obtengo cuatro grupos de clientes basados ​​en la proximidad.

cluster_obj <- kmeans(customer_df,centers=customer_df[initial_centers(customer_df,4),])
head(cluster_obj)
## $cluster
##    [1] 1 4 2 1 3 3 3 1 2 1 3 2 2 4 3 4 4 4 3 4 3 2 3 4 2 3 2 3 1 4 4 4 1 1 4 2 2
##   [38] 2 4 4 3 3 1 2 4 1 2 1 3 1 2 2 3 3 4 1 4 2 3 3 2 4 2 2 3 2 1 4 2 2 2 4 4 2
##   [75] 4 3 3 4 1 1 1 3 3 2 1 1 3 3 4 4 3 1 2 4 3 1 3 2 2 2 3 2 3 4 4 2 3 3 1 3 1
##  [112] 2 2 4 1 1 1 3 4 1 2 3 3 3 1 1 2 3 3 2 1 3 4 2 2 3 2 2 1 2 1 2 2 2 2 3 2 3
##  [149] 1 2 2 1 2 3 2 2 1 4 2 4 3 3 3 2 1 1 2 2 3 3 4 1 2 4 1 2 1 2 3 2 2 2 3 3 2
##  [186] 1 1 1 4 3 4 4 2 1 3 2 4 2 2 3 3 1 3 2 3 2 4 2 3 2 4 1 1 3 1 2 1 3 4 2 4 3
##  [223] 4 2 4 3 4 2 4 2 1 2 1 3 4 2 2 3 2 4 2 1 2 3 3 2 2 3 3 1 3 4 4 3 4 1 1 2 3
##  [260] 3 4 2 1 1 1 2 2 2 1 4 4 3 1 2 4 3 3 3 3 3 3 3 2 3 3 3 3 2 2 3 3 1 4 1 2 1
##  [297] 4 2 2 3 1 4 4 2 3 3 2 4 4 3 2 1 2 3 2 2 4 4 2 2 2 3 2 2 2 2 2 2 2 1 2 2 4
##  [334] 3 3 2 2 3 3 1 2 4 2 1 3 3 4 1 2 4 1 4 4 4 1 2 3 1 3 1 3 3 2 3 4 1 2 2 2 2
##  [371] 1 2 2 2 1 3 2 1 2 2 2 4 3 2 2 3 1 3 3 4 1 1 3 4 2 4 1 1 4 4 2 4 2 3 3 2 4
##  [408] 4 4 3 2 1 3 3 4 1 3 3 1 3 4 2 3 2 2 3 2 2 2 1 2 3 4 3 4 3 4 4 2 1 3 2 3 1
##  [445] 3 1 1 2 3 3 2 2 3 4 1 1 3 1 2 4 2 2 2 3 1 3 2 1 4 2 3 2 4 1 4 3 1 1 4 4 3
##  [482] 1 2 4 3 3 2 1 4 2 3 2 4 3 4 4 1 2 2 2 3 3 4 4 1 3 2 3 2 4 1 2 4 1 2 3 1 3
##  [519] 2 3 3 3 1 3 2 4 1 3 4 3 4 4 3 4 4 2 1 1 3 3 3 3 3 4 2 1 3 3 1 1 4 1 4 2 2
##  [556] 1 1 4 4 3 3 4 3 1 4 3 1 2 3 3 2 4 1 2 3 3 1 2 2 1 3 1 4 4 3 2 4 3 1 4 2 3
##  [593] 3 2 2 1 1 2 4 2 3 3 2 1 4 1 4 3 3 3 3 3 3 2 2 2 1 1 2 3 2 1 1 2 1 1 1 1 1
##  [630] 2 4 2 1 1 3 1 4 2 4 2 2 1 4 1 2 2 3 1 1 3 1 1 3 4 3 2 4 1 1 1 2 1 1 1 2 3
##  [667] 4 3 2 4 4 4 2 4 4 3 2 1 2 2 3 3 3 4 2 4 3 1 2 4 2 3 1 3 3 1 4 3 4 4 1 2 3
##  [704] 3 4 4 2 2 1 2 2 1 3 4 1 2 2 3 4 4 2 3 1 2 4 3 1 2 2 2 1 4 1 3 1 4 2 2 1 1
##  [741] 2 2 2 2 1 2 4 3 3 3 1 3 4 1 1 3 2 1 4 4 2 4 2 3 2 3 3 4 2 1 2 3 2 1 1 1 3
##  [778] 2 3 4 3 2 2 4 1 4 4 2 2 1 1 2 3 1 2 2 2 1 4 3 3 3 1 2 1 3 2 4 2 3 4 1 4 3
##  [815] 1 3 2 2 1 1 2 3 4 4 4 3 1 2 4 2 2 2 1 3 4 4 2 2 3 2 4 3 4 2 2 2 3 3 3 4 2
##  [852] 3 3 3 1 1 3 1 1 2 2 1 3 3 4 3 3 3 2 2 1 3 2 3 1 4 3 2 4 1 4 3 3 2 3 4 4 1
##  [889] 3 1 2 4 4 3 2 1 2 3 2 1 1 2 3 2 1 1 3 3 4 3 3 4 3 3 3 2 2 1 2 3 1 1 1 4 2
##  [926] 3 4 2 4 1 4 3 4 4 1 3 2 2 1 2 2 4 2 4 1 4 1 2 1 2 4 3 4 2 4 4 4 2 4 1 2 3
##  [963] 3 2 4 4 4 2 4 4 3 2 1 2 4 3 2 3 1 2 3 4 1 4 3 4 2 1 4 1 4 2 3 3 1 1 2 2 2
## [1000] 4
## 
## $centers
##          lat       long
## 1 -44.672042  103.20907
## 2   9.621406  -22.15262
## 3  -4.487789 -127.84173
## 4  48.358322  110.24174
## 
## $totss
## [1] 13417586
## 
## $withinss
## [1]  557304.2 1006745.4  962130.0  492832.8
## 
## $tot.withinss
## [1] 3019012
## 
## $betweenss
## [1] 10398574

Arriba verá el encabezado del objeto de resultado devuelto por la función kmeans. A continuación, combino los índices de clúster contenidos por el objeto kmeans con el marco de datos del cliente, de modo que ahora tenemos 3 columnas. Esto nos permitirá hacer ggplots, etc.

result_df <- customer_df
result_df$group <- cluster_obj$cluster
head(result_df)
##         lat        long group
## 1 -42.69660   58.067160     1
## 2  37.31715  179.655272     4
## 3 -28.68660   -3.025719     2
## 4 -76.15463  117.119388     1
## 5 -14.84898 -162.408406     3
## 6  54.19468 -128.476143     3

Completo esta publicación visualizando los resultados en un ggplot (diagrama de dispersión usando el paquete ggplot2 R). Para colorear utilicé el paquete viridis en R:

library(ggplot2)
library(viridis)
## Loading required package: viridisLite
ggplot(result_df) + geom_point(mapping = aes(x=lat,y=long,color=group)) +
  xlim(-90,90) + ylim(-180,180) + scale_color_viridis(discrete = FALSE, option = "D") + scale_fill_viridis(discrete = FALSE) 

Hagamos otra prueba con 20 almacenes:

cluster_obj <- kmeans(customer_df,centers=customer_df[initial_centers(customer_df,20),])
result_df$group <- cluster_obj$cluster
ggplot(result_df) + geom_point(mapping = aes(x=lat,y=long,color=group)) +
  xlim(-90,90) + ylim(-180,180) + scale_color_viridis(discrete = FALSE, option = "D") + scale_fill_viridis(discrete = FALSE)

Leave a Reply

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *

Este sitio usa Akismet para reducir el spam. Aprende cómo se procesan los datos de tus comentarios.

Close

Meta