将客户打包成桶

时间:2016-11-10 17:46:33

标签: r statistics k-means bin-packing

我说有25位客户。每个客户都有我们系统的许多用户,例如客户1有45个用户,客户2有46个用户...客户25有1000个用户。

我想将每个客户分成一个桶,每个桶包含大致相同数量的用户。我知道我总共需要5个桶。

(这里的存储桶代表服务器,我想将我的客户端分配到每个服务器的用户总数大致相等的不同服务器,以防止服务器过载.1客户端必须在同一台服务器上(即无法将1个客户端拆分为2台服务器。)

是否有合适的方法将客户分配到存储桶?我认为一些聚类方法可能会起作用(我尝试使用R的kmeans),但我似乎无法找到规定每个聚类中的用户总数大致相同的方法。

这是我的R代码作为我迄今为止所做的一个例子:

#Create dataset
r <- data.frame(users=c(1000, 960, 920, 870, 850, 700, 600, 550, 520, 500, 420, 400, 390, 300, 210, 200, 160, 80, 70, 50, 49, 48, 47, 46, 45))
#Try kmeans clustering
fit <- kmeans(r, 5) 
#get cluster means
aggregate(r, by=list(fit$cluster),FUN = mean)
#append cluster assignment
r <- data.frame(r,fit$cluster)

#Plot cluster
library(cluster)
clusplot(r, fit$cluster, color=TRUE, shade=TRUE, labels=2, lines=0)
library(fpc)
plotcluster(r, fit$cluster)

这将我的客户聚集到存储桶中,但每个存储桶中的用户数量大致不相等。

我已经将此标记为R问题,但如果在其他一些软件包中有一个简单的解决方案我会全力以赴:-)

2 个答案:

答案 0 :(得分:1)

不是尝试聚类(它解决了一个非常不同的问题,即将相似的值放入聚类中),而是在这里有bin packing problem的经典变体。

这些往往是NP难的,因此寻找最佳解决方案非常昂贵。相反,尝试一个贪婪的策略:估计最小桶大小为总/桶。按降序尺寸处理元素,并始终将它们放入具有最多可用空间的存储桶中。为了获得更好的结果,添加一个优化函数,如果这样可以改善结果,则可以在成对的桶之间交换元素。如果你有很多小值,这样的策略可能会很好用。

答案 1 :(得分:1)

我不知道这种“恒定和采样”的推荐解决方案是什么。这是我的镜头 - 对项目进行排序,转换为矩阵,每列代表一个样本,每隔一行反转一次。

以下是代码:

set.seed(1024)
r <- data.frame(users=c(1000, 960, 920, 870, 850, 700, 600, 550, 520, 500, 420, 400, 390, 300, 210, 200, 160, 80, 70, 50, 49, 48, 47, 46, 45))

a<-   r$users #runif(n = 25, 100,400) #rnorm(25,100,100) # 1:25
#hist(a)
df<- data.frame(id=1:25,x=a)

# sort 
x<- df$id[order(df$x)]
# convert to matrix
#each column of this matrix represetns one sample
xm<-matrix(x,ncol=5,byrow = T); xm
oldsum<-apply(matrix(df$x,ncol=5,byrow = T), 2,sum)

#flip alternate rows of this sorted matrix
i= 1:nrow(xm)
im=i[c(F,T)]
xm[im,]
xm[im,]<- rev(xm[im,])

# new matrix of indeices 
xm

#hence the new matrix of values
xm2<- matrix(a[c(xm)],ncol = 5, byrow = F)
xm
xm2

newsum<- (apply(xm2, 2,sum))

# improvement
rbind(oldsum,newsum)
barplot(rbind(oldsum,newsum)[1,])
barplot(rbind(oldsum,newsum)[2,])

# each column of following matrix represents one sample 
#(values are indices in original vector a)
xm