Localização de vários armazéns no centro

Em uma postagem anterior, mostrei como um único problema de localização de depósito pode ser abordado localizando o depósito próximo ao seu centro de massa. Nesta postagem, queremos localizar vários armazéns em seu centro de massa.

Utilizaremos as funções já definidas nos posts anteriores.

Em  http://www.supplychaindataanalytics.com/single-warehouse-problem-locating-warehouse-at-center-of-mass-using-r/  forneci uma função para localizar um único depósito em seu centro de massa.

Em  http://www.supplychaindataanalytics.com/proximity-based-spatial-customer-grouping-in-r  , mostrei como agrupar clientes com base no agrupamento de proximidade espacial.

# example see here: http://www.supplychaindataanalytics.com/single-warehouse-problem-locating-warehouse-at-center-of-mass-using-r/
center_of_mass <- function(x,y,w){
  c(crossprod(x,w)/sum(w),crossprod(y,w)/sum(w))
}

# example see here: http://www.supplychaindataanalytics.com/proximity-based-spatial-customer-grouping-in-r
initial_centers <- function(customers,centers){
  quantiles <- c()
  for(i in 1:centers){
    quantiles <- c(quantiles,i*as.integer(nrow(customers)/centers))
  }
  quantiles
}

Combinaremos essas duas abordagens para resolver um problema de localização de vários armazéns usando a teoria do centro de massa. Esta abordagem é aplicável quando já sabemos quantos armazéns queremos operar. A abordagem do post em questão não será suficiente para resolver um problema em que ainda não sabemos quantos armazéns realmente queremos operar.

Começo criando um dataframe com 1000 clientes distribuídos aleatoriamente com demanda distribuída aleatoriamente

customer_df <- as.data.frame(matrix(nrow=1000,ncol=3))
colnames(customer_df) <- c("lat","long","demand")
customer_df$lat <- runif(n=1000,min=-90,max=90)
customer_df$long <- runif(n=1000,min=-180,max=180)
customer_df$demand <- runif(n=1000,min=0,max=10)
head(customer_df)
##         lat       long   demand
## 1 -42.50378  137.62188 9.608067
## 2  47.79308  101.30536 9.510299
## 3 -14.17326   24.38595 1.610305
## 4 -85.34352 -151.29061 6.394425
## 5 -26.31244  112.75030 6.972434
## 6  55.01428   58.17198 2.797564

Em seguida, agrupo os clientes usando a abordagem mostrada em um post anterior e aplicando a função definida initial_centers. Quero localizar 20 armazéns, então agrupo os clientes em 20 grupos.

centeroids <- initial_centers(customer_df[,-3],20)
cluster_obj <- kmeans(customer_df[,-3],centers = customer_df[centeroids,-3])
customer_df$group <- cluster_obj$cluster
head(customer_df)
##         lat       long   demand group
## 1 -42.50378  137.62188 9.608067     2
## 2  47.79308  101.30536 9.510299     4
## 3 -14.17326   24.38595 1.610305     6
## 4 -85.34352 -151.29061 6.394425     8
## 5 -26.31244  112.75030 6.972434    18
## 6  55.01428   58.17198 2.797564    16

Conforme exibido acima, adicionei o índice de grupo baseado em cluster ao dataframe do cliente.

Agora, definirei uma função que percorrerá cada grupo de clientes e identificará o centro de massa. O requisito é que um dataframe seja inserido, contendo uma coluna de latitude, longitude, demanda e grupo – exatamente neste formato:

multiple_centers_of_mass <- function(df){
  result_df <- as.data.frame(matrix(nrow=nrow(df),ncol=6))
  colnames(result_df) <- c("lat","long","demand","group","com_lat","com_long")
  result_df[,c(1,2,3,4)] <- df
  for(i in 1:length(unique(df[,4]))){
    sub_df <- result_df[result_df$group==i,]
    com <- center_of_mass(sub_df$lat,sub_df$long,sub_df$demand)
    result_df$com_lat[result_df$group==i] <- com[1]
    result_df$com_long[result_df$group==i] <- com[2]
  }
  result_df
}

Vamos testar a função multiple_centers_of_mass que acabei de definir:

com_df <- multiple_centers_of_mass(customer_df)
head(com_df)
##         lat       long   demand group   com_lat   com_long
## 1 -42.50378  137.62188 9.608067     2 -25.97973  158.17382
## 2  47.79308  101.30536 9.510299     4  63.58158   84.91329
## 3 -14.17326   24.38595 1.610305     6 -21.20417   26.80993
## 4 -85.34352 -151.29061 6.394425     8 -64.12072 -145.48419
## 5 -26.31244  112.75030 6.972434    18 -33.15564   99.15738
## 6  55.01428   58.17198 2.797564    16  35.04988   44.42388

Vamos visualizar os resultados do teste usando um gráfico de dispersão do pacote ggplot2 R. Abaixo você vê as localizações dos armazéns (centros de massa):

library(ggplot2)

lat_wh_vc <- unique(com_df$com_lat)
long_wh_vc <- unique(com_df$com_long)
warehouse_df <- as.data.frame(matrix(nrow=length(lat_wh_vc),ncol=2))
warehouse_df[,1] <- lat_wh_vc
warehouse_df[,2] <- long_wh_vc
colnames(warehouse_df) <- c("lat","long")
ggplot(warehouse_df) + geom_point(mapping = aes(x=lat,y=long)) + xlim(-90,90) + ylim(-180,180)

Os clientes estão agrupados conforme abaixo:

library(viridis)
## Warning: package 'viridis' was built under R version 3.5.3
## Loading required package: viridisLite
ggplot(com_df) + geom_point(mapping = aes(x=lat,y=long,color=group,size=demand)) +
  xlim(-90,90) + ylim(-180,180) + scale_color_viridis(discrete = FALSE, option = "D") + scale_fill_viridis(discrete = FALSE) 

Leave a Reply

Deixe um comentário

O seu endereço de e-mail não será publicado. Campos obrigatórios são marcados com *

Esse site utiliza o Akismet para reduzir spam. Aprenda como seus dados de comentários são processados.

Close

Meta