按周对多个特征进行聚类

Posted

技术标签:

【中文标题】按周对多个特征进行聚类【英文标题】:Clustering with multiple features by week 【发布时间】:2016-12-30 01:42:38 【问题描述】:

我有一组按商店按周列出的数据,其中包含 2 个特征 - 销售额和 pp。我想根据这些特征对它们进行聚类,理想情况下对全年交易模式最相似的数据进行分组。

是否可以使用我拥有的数据来做到这一点。我的理解是特征是列,行是根据集群分配标签的内容,但我有几周的时间要考虑,所以我不知道这些应该在行还是列中?

library(data.table)
dt <- data.table(weeks = rep(seq(1:5),5),
             store = c(rep("a", 5), rep("b", 5), rep("c", 5), 
                       rep("e", 5), rep("d", 5)),
             sales = rep(rnorm(5), 5),
             pp = rep(rnorm(5), 5))
dt <- dcast.data.table(dt, store ~ weeks, value.var = c("sales", "pp"))

谢谢

【问题讨论】:

您是否认为商店的集群相对于 (sales,pp) 每周都在变化。 是的,数据中有超过 1,000 家商店,其中一些将位于高旅游地点,因此当天气真的很热等时,他们商店的数据会出现峰值。所以我期待说在这很明显的商店中,可能还有一个基于 pp 指标的子集。通常我只是采用平均每周销售额/pp 并使用它,因此删除了各个周,但我希望也能够捕捉到全年每周的变化。 【参考方案1】:

由于您拥有超过 1000 家商店,以下演示可能无法直接应用,但希望为您指明正确的方向。

您可以每周或任何其他周的变体分析商店集群(N=4,8,...)

在这里,我们以每周的频率查看商店集群:

测试数据

library(dplyr)     #data manipulation
library(ggdendro)  #extracting clusters
library(ggplot2)   #plotting
library(gridExtra) #for arranging ggplot graphs in grids 

set.seed(42)

DF <- data.frame(weeks = rep(seq(1:5),5),
    store = c(rep("A", 5), rep("B", 5), rep("C", 5), 
            rep("E", 5), rep("D", 5)),
    sales = rnorm(25),
    pp = rnorm(25))


weekInput = unique(DF$weeks)

选择周频率:

在简单的情况下,我包括了离散的周,即 1、2、3、4 和 5。

假设您希望选择 N = 4 作为周频率,即周 1 到 4、5 到 8 等,您可以使用以下方法创建一年中的 weekInput 分区并根据您的要求进行修改。

#weekFreq = 4
#StartWeek = 1
#EndWeek = 52
#startPoints=seq(StartWeek,EndWeek,weekFreq)    
#endPoints= c(tail(startPoints,-1)-1,EndWeek)
#
#freqDF = data.frame(cbind(startPoints,endPoints))
#weekInput = lapply(1:nrow(freqDF),function(x)  z= freqDF[x,]; z=as.vector(as.matrix(z))  )
#head(weekInput)
#[[1]]
#[1] 1 4
#
#[[2]]
#[1] 5 8
#
#[[3]]
#[1]  9 12
#
#[[4]]
#[1] 13 16
#
#[[5]]
#[1] 17 20
#
#[[6]]
#[1] 21 24

绘制聚类

绘制各种树状图的好资源是here 和here

我们每周计算数值数据上的距离矩阵并创建层次聚类并使用 ggdendro 包进行绘图并输出绘图对象列表

plotList = lapply(weekInput,function(x) 

subsetWeek=DF %>% 
  group_by(weeks) %>% 
  filter(weeks==x) %>%  #you could change this to `weeks %in% c(x[1],x[2])`
  as.data.frame()  %>%  # x[1] and x[2] are start and end points of weekInput
  select(-weeks) %>% 
  as.data.frame()

#For numeric features of data, compute the distance matrix and form hierarchical cluster

numericDF= subsetWeek[,sapply(subsetWeek,is.numeric)]

clustDF = hclust(dist(numericDF))

#You can choose to limit the clusters to N = n, as per your discretion
#clustDF =  cutree(clustDF, 4)


clustDF$labels = subsetWeek$store

#Use functions from ggdendro package for extracting clusters for ease in plotting

clustDendro = as.dendrogram(clustDF)

dendroData = dendro_data(clustDendro,type="rectangle")

Labels = label(dendroData)
Labels$group <- c(rep("Area1", 2), rep("Area2", 2), rep("Area3", 1))


gPlot = ggplot(segment(dendroData)) +
    geom_segment(aes(x=x,y=y,xend=xend,yend=yend)) + 
    geom_label(data=Labels,aes(label=label,x=x,y=0,label.size=5,colour=Labels$group,fontface="bold")) +
    ggtitle(paste0("Store Clusters for Week:",x)) +
    labs(color="Area Names\n")


gPlot = gPlot + theme(legend.title = element_text(face = "bold"))

return(gPlot)


)

安排情节

上面的绘图对象列表可以根据需要排列。 有关更多详细信息的有用链接是here

grid::grid.newpage()
grid::grid.draw(do.call(rbind,lapply(plotList,function(x) ggplotGrob(x))))

单周:

所有周

由于单列排列,可读性略有影响

【讨论】:

以上是关于按周对多个特征进行聚类的主要内容,如果未能解决你的问题,请参考以下文章

按周分组和求和

如何使用非常小的数据集对特征进行加权以获得更好的聚类?

使用聚类数据进行 Sklearn 回归

简单介绍聚类算法

借助 GPU 支持对高维数据进行更快的 Kmeans 聚类

机器学习-层次聚类(划分聚类)