【问题标题】:Clustering or bucketing users based on rule根据规则对用户进行聚类或分桶
【发布时间】:2023-03-03 10:16:01
【问题描述】:

需要根据产品和集群大小对数据进行聚类。这是一个可重现的示例:

library(data.table)
mydata <-  fread('User_ID,Product
      A,"P1"
      B,"P1"
      C,"P1"
      D,"P1"
      E,"P2"
      F,"P2"
      G,"P3"
      H,"P3"
      I,"P3"
      J,"P3"
      K,"P3"
      L,"P3"
      M,"P3"')

集群的最大大小不能大于 3。而且每个集群只能包含一种产品。 我正在寻找的输出是:

Output <-  fread('User_ID,Product,Cluster
      A,"P1",1
      B,"P1",1
      C,"P1",1
      D,"P1",2
      E,"P2",3
      F,"P2",3
      G,"P3",4
      H,"P3",4
      I,"P3",4
      J,"P3",5
      K,"P3",5
      L,"P3",5
      M,"P3",6')

【问题讨论】:

    标签: r data.table grouping


    【解决方案1】:

    这是另一个解决方案:

    my_data_grp <- mydata %>%
      group_by(Product) %>%
      summarise(count= n())
    
    my_data_grp$counter <- 1:nrow(my_data_grp)
    mydata <- merge(mydata,my_data_grp,by = 'Product')
    cnt=0
    fin=data.frame()
    for (i in 1:nrow(my_data_grp)){
      temp= mydata %>%
        filter(counter==my_data_grp$counter[i])
      #print(final_ProductGrp$cnt[i])
      temp$index = 1:nrow(temp)
      temp$quotient = ceiling(temp$index/3)+cnt
      cnt=max(temp$quotient)
      fin <- rbind(fin,temp)
    }
    View(fin)
    

    提供所需的输出。

    【讨论】:

      【解决方案2】:

      这是一个 data.table 方法。

      mydata[, cluster := as.integer(factor(paste(Product, (rowid(Product) - 1L) %/% 3)))]
      

      这个想法是粘贴带有rowid of product 输出的产品,它单独计入每个产品。从此计数中减去 1 并使用 %/% 获得整数除法结果。将字符向量转换为因子,这将按字典顺序对数据进行排序,然后再转换为整数。

      返回

      mydata
          User_ID Product cluster
       1:       A      P1       1
       2:       B      P1       1
       3:       C      P1       1
       4:       D      P1       2
       5:       E      P2       3
       6:       F      P2       3
       7:       G      P3       4
       8:       H      P3       4
       9:       I      P3       4
      10:       J      P3       5
      11:       K      P3       5
      12:       L      P3       5
      13:       M      P3       6
      

      效率的潜在改进是使用interaction 代替paste / factor,如下所示:

      mydata[, cluster := as.integer(interaction(Product, (rowid(Product) - 1L) %/% 3,
                                                 lex.order=TRUE))]
      

      返回的值仍然是正确聚类的,并且是有序的,但它们不直接遵循自然数序列。

      mydata
          User_ID Product cluster
       1:       A      P1       1
       2:       B      P1       1
       3:       C      P1       1
       4:       D      P1       2
       5:       E      P2       4
       6:       F      P2       4
       7:       G      P3       7
       8:       H      P3       7
       9:       I      P3       7
      10:       J      P3       8
      11:       K      P3       8
      12:       L      P3       8
      13:       M      P3       9
      

      【讨论】:

      • 是的,你的方式很有趣。我花了40分钟。那不是。
      • 谢谢。足够近!! .但是我添加了另一个解决方案。给出准确的输出
      【解决方案3】:

      请试试这个。我希望这可以进一步优化:

      test=mydata%>%group_by(Product)%>%mutate(count = n())%>%ungroup()
      .GlobalEnv$counter = 0;
      
      clust = ddply(.data = test,.variables = c('Product'),function(t){
            if(t$count[1]<=3){
                .GlobalEnv$counter=.GlobalEnv$counter+1;  
                Cluster = rep(.GlobalEnv$counter,t$count[1])
                t = cbind(t,Cluster)
            }else{
                .GlobalEnv$counter=.GlobalEnv$counter+1;
                factor=floor(t$count[1]/3);
                if(t$count[1]%%3==0){
                      Cluster = rep(seq(.GlobalEnv$counter,.GlobalEnv$counter+(factor-1),by = 1),each=3)
                      t = cbind(t,Cluster)
                  }else{
                      tempclust = rep(seq(.GlobalEnv$counter,.GlobalEnv$counter+(factor-1),by = 1),each=3)
                      .GlobalEnv$counter = .GlobalEnv$counter+factor
                      Cluster = c(tempclust,rep(.GlobalEnv$counter,each=(t$count[1]%%3)))
                      t = cbind(t,Cluster)
                  }
        }})
      clust%>%select(Product,User_ID,Cluster)
      
      #    Product User_ID Cluster
      #1       P1       A       1
      #2       P1       B       1
      #3       P1       C       1
      #4       P1       D       2
      #5       P2       E       3
      #6       P2       F       3
      #7       P3       G       4
      #8       P3       H       4
      #9       P3       I       4
      #10      P3       J       5
      #11      P3       K       5
      #12      P3       L       5
      #13      P3       M       6
      

      此逻辑可能仅适用于奇数组长度,在这种情况下为 3。

      【讨论】:

        猜你喜欢
        • 2014-07-19
        • 1970-01-01
        • 2012-03-26
        • 1970-01-01
        • 2013-12-05
        • 2017-11-22
        • 1970-01-01
        • 2020-12-29
        • 1970-01-01
        相关资源
        最近更新 更多