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

时间:2018-10-05 06:50:42

标签: r

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

    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")

我们可以看到第一列告诉我们订单号,其余各列告诉我们该订单属于。此外,如果type_ *列填充为0,则它​​不相关。

我想创建一个新列,该列根据“订单描述”-> type_ *列定义组。例如,对于订单1和订单5,我们有相同的type_ *列,其中未填充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列以上type_ *->其中大约有10-15列!

感谢帮助!

3 个答案:

答案 0 :(得分:8)

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

> 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

答案 1 :(得分:2)

data.table解决方案

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

答案 2 :(得分:1)

在某些情况下这可能会失败,但这是一个有趣的答案,因为我们可以将R用于其实际构建的目的。统计编程。

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

k均值聚类的性质是,“总是” 0列倾向于对结果具有很强的分类效果。

注意:

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

2)我们应该避免使用变量名data,因为它是基数R中的一个函数。