基于另外两列映射新数据框列的最快方法

时间:2015-04-01 17:33:21

标签: r

我的数据框看起来像这样:

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

我知道我可以遍历它并分配类别,但我的问题是是否有更快的矢量化方式?

1 个答案:

答案 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))