我的数据框看起来像这样:
id|value
01| 100
01| 101
01| 300 #edited for case I originally left out
02| 300
03| 100
03| 101
04| 100
我想添加一个新列,查看id和分配给每个id的值。
例如: 如果id同时具有值100和101,我将其添加到类别a。 如果id的值为300,我会将其添加到类别b中。 如果id只有一个值(100或101,而不是两者),则将其分配给类别c。
结果:
id|value|category
01| 100 | a
01| 101 | a
01| 300 | b #edited for case I originally left out
02| 300 | b
03| 100 | a
03| 101 | a
04| 100 | c
我知道我可以遍历它并分配类别,但我的问题是是否有更快的矢量化方式?
答案 0 :(得分:2)
data.table
我们可以获得每个' id'这是' 100'' 101'并将它们加在一起。输出将是0,1或2,对应于无,单个元素或两者都存在。这可以转换为factor
并更改labels
,以便' a'将是' 2'' b'作为' 0'和' c' as' 1'。
library(data.table)
setDT(df2)[, indx:=sum(unique(value)==100)+sum(unique(value)==101),
id][, category:=factor(indx, levels=c(2,0,1), labels=letters[1:3]) ][,
indx:=NULL][]
# id value category
#1: 1 100 a
#2: 1 101 a
#3: 2 300 b
#4: 3 100 a
#5: 3 101 a
#6: 4 100 c
或者我们可以创建一个命名向量(' v1')并将其用作索引来映射按' id'分组的字符元素(toString(...)
)。
v1 <- c('100, 101' = 'a', '300'='b', '100'= 'c', '101'='c')
setDT(df2)[, category := v1[toString(sort(unique(value)))], by=id][]
# id value category
#1: 1 100 a
#2: 1 101 a
#3: 2 300 b
#4: 3 100 a
#5: 3 101 a
#6: 4 100 c
基于新数据集和新条件,我们可以将第一个解决方案修改为
setDT(df3)[, indx:= sum(unique(value)==100) + sum(unique(value)==101), id][,
category:= factor(indx, levels=c(2,0,1), labels=letters[1:3])][
value==300, category:='b'][, indx:=NULL][]
# id value category
#1: 1 100 a
#2: 1 101 a
#3: 1 300 b
#4: 2 300 b
#5: 3 100 a
#6: 3 101 a
#7: 4 100 c
或使用第二个选项
v1 <- c('100, 101' = 'a', '100, 101, 300' = 'a', '300'='b',
'100'= 'c', '101'='c')
setDT(df3)[, category := v1[toString(sort(unique(value)))],
by=id][value==300, category := 'b'][]
# id value category
#1: 1 100 a
#2: 1 101 a
#3: 1 300 b
#4: 2 300 b
#5: 3 100 a
#6: 3 101 a
#7: 4 100 c
df2 <- structure(list(id = c(1L, 1L, 2L, 3L, 3L, 4L), value = c(100L,
101L, 300L, 100L, 101L, 100L)), .Names = c("id", "value"),
row.names = c(NA, -6L), class = "data.frame")
df3 <- structure(list(id = c(1L, 1L, 1L, 2L, 3L, 3L, 4L),
value = c(100L, 101L, 300L, 300L, 100L, 101L, 100L)),
.Names = c("id", "value"), class = "data.frame",
row.names = c(NA, -7L))