代码之家  ›  专栏  ›  技术社区  ›  Mal_a

基于非零填充列组合创建组

r
  •  4
  • Mal_a  · 技术社区  · 6 年前

    我很难解决这个问题。我将在示例的基础上对其进行最好的解释,让我们看看以下数据:

        order type_a type_b type_c type_d
    1     1      0     50     10      0
    2     2     10      0      0     80
    3     3     15      0      0     35
    4     4      0      0     30      0
    5     5      0     20     40      0
    

    dput :

    data <- structure(list(order = c(1, 2, 3, 4, 5), type_a = c(0, 10, 15, 
    0, 0), type_b = c(50, 0, 0, 0, 20), type_c = c(10, 0, 0, 30, 
    40), type_d = c(0, 80, 35, 0, 0)), .Names = c("order", "type_a", 
    "type_b", "type_c", "type_d"), row.names = c(NA, -5L), class = "data.frame")
    

    我们可以看到第一列告诉我们订单号,其余的列告诉我们什么 属于

    我想创建一个新列来定义基于“订单描述”的组-->键入*列。例如,订单1&顺序5,我们有相同类型的*列,但不填充0值,因此它们属于同一组,顺序2和;3等。

       order type_a type_b type_c type_d   group
    1     1      0     50     10      0 group_1
    2     2     10      0      0     80 group_2
    3     3     15     10      0     35 group_2
    4     4      0      0     30      0 group_3
    5     5      0     20     40      0 group_1
    

    仅供参考,在我的真实数据中,我有4列以上的类型*-->大约有10-15个!

    3 回复  |  直到 6 年前
        1
  •  8
  •   Spacedman    6 年前

    您的组由第2列到第5列中是否存在0来定义。测试0时,将真/假值折叠为一个字符串,您将得到每个组的唯一字符串。转换为因子:

    > data$group = factor(apply(data[,2:5] ==0,1,paste,collapse=""))
    > data
      order type_a type_b type_c type_d              group
    1     1      0     50     10      0 TRUEFALSEFALSETRUE
    2     2     10      0      0     80 FALSETRUETRUEFALSE
    3     3     15      0      0     35 FALSETRUETRUEFALSE
    4     4      0      0     30      0  TRUETRUEFALSETRUE
    5     5      0     20     40      0 TRUEFALSEFALSETRUE
    

    现在名称很难看,所以更改级别:

    > class(data$group)
    [1] "factor"
    > levels(data$group)=paste("group_",1:length(levels(data$group)))
    > data
      order type_a type_b type_c type_d    group
    1     1      0     50     10      0 group_ 2
    2     2     10      0      0     80 group_ 1
    3     3     15      0      0     35 group_ 1
    4     4      0      0     30      0 group_ 3
    5     5      0     20     40      0 group_ 2
    

    如果所有这些大写的TRUEFALSE都伤害了你的眼睛,那么一个简单的修复程序将生成一个整洁的二进制数:

    > data$group = factor(apply(0+(data[,2:5] ==0),1,paste,collapse=""))
    > data
      order type_a type_b type_c type_d group
    1     1      0     50     10      0  1001
    2     2     10      0      0     80  0110
    3     3     15      0      0     35  0110
    4     4      0      0     30      0  1101
    5     5      0     20     40      0  1001
    
        2
  •  2
  •   Wimpel    6 年前

    数据表解决方案

    library(data.table)
    
    setDT(data)[, id := .GRP, by = list( do.call(paste0, c( data.frame( data[,2:5] != 0 ) ) ) ) ][, id := paste0( "Group_", id)][]
    
    #    order type_a type_b type_c type_d      id
    # 1:     1      0     50     10      0 Group_1
    # 2:     2     10      0      0     80 Group_2
    # 3:     3     15      0      0     35 Group_2
    # 4:     4      0      0     30      0 Group_3
    # 5:     5      0     20     40      0 Group_1
    
        3
  •  1
  •   Brandon Bertelsen    6 年前

    set.seed(42)
    cols <- grep("type_", names(d))
    d$group <- kmeans(d[cols], 4)$cluster
    # d$group <- paste0("group_", d$group)
    

    k-means聚类的本质是“总是”0列往往对结果有很强的分类效果。

    1) 我们使用 grep 标识列,因为如果数据的形状不同或位置发生变化,则对列名使用数字引用会导致将来出现问题。其他人查看您的代码时,它的可读性也更高。

    2) 我们应该避免使用变量名 data