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)
Cientista de dados com foco em simulação, otimização e modelagem em R, SQL, VBA e Python
Leave a Reply