以质量中心定位多个仓库(使用R)

在上一篇文章中,我展示了如何通过将仓库定位在其质量中心附近来解决单个仓库的位置问题。在这篇文章中,我们希望将多个仓库定位在其质量中心。

我们将使用之前文章中已经定义的函数。

# 计算加权质量中心的函数。
center_of_mass <- function(x,y,w){
  c(crossprod(x,w)/sum(w),crossprod(y,w)/sum(w))
}

# 用于指定初始中心的函数
initial_centers <- function(customers,centers){
  quantiles <- c()
  for(i in 1:centers){
    quantiles <- c(quantiles,i*as.integer(nrow(customers)/centers))
  }
  quantiles
}

我们将把这两种方法结合起来,利用质量中心理论解决多个仓库的位置问题。这种方法适用于我们已经知道要经营多少个仓库的时候。如果我们还不知道我们实际要经营多少个仓库,那么本帖中的方法就不足以解决这个问题。

我首先创建一个数据框架,里面有1000个随机分布的客户,需求随机分布。

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

接下来,我用上一篇文章中展示的方法,应用定义的函数initial_centers对客户进行分组。我想定位20个仓库,所以我把客户分成20组。

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

如上图所示,我将基于聚类的组索引添加到客户数据框架中。

现在,我将定义一个函数,该函数将循环浏览每个客户群,并确定质量中心。需求是必须输入一个数据框,包含经纬度、需求和组列–格式如下。

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
}

让我们测试一下我刚才定义的multiple_centers_of_mass 功能。

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

让我们使用ggplot2 R包中的散点图将测试结果可视化。下面你可以看到仓库位置(质量中心)。

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)

客户的分组如下图所示。

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

发表评论

您的电子邮箱地址不会被公开。 必填项已用*标注

此站点使用Akismet来减少垃圾评论。了解我们如何处理您的评论数据

Close

功能