r - 根据另一列的文本,整理 data.table 每行不同列的数据

标签 r data.table

我想向我的 data.table 添加一个新列,其中包含来自其他列之一的数据。但是,列的选择因行而异 - 取决于另一列的内容。所以:

对于数据集:

     a_data b_data column_choice
[1,]     55      1             a
[2,]     56      2             a
[3,]     57      3             b

产生于:
dat=data.table(a_data = c(55, 56, 57), 
               b_data = c(1,  2,  3), 
               column_choice = c("a", "a", "b"))

我想要一个新列“选择”,它包含(每行)来自“a_data”或“b_data”的数据,具体取决于“column_choice”的值。因此,生成的数据表将是:
     a_data b_data column_choice chosen
[1,]     55      1             a     55
[2,]     56      2             a     56
[3,]     57      3             b      3

我设法使用以下方法获得了所需的效果:
dat=dat[, data.table(.SD, chosen=.SD[[paste0(.SD$column_choice, "_data")]]),
        by=1:nrow(a)]
dat$nrow = NULL

但是这感觉很笨重;也许有一种更简单的方法来做到这一点(这无疑也会教我一些关于 R 的知识)?

在实践中,数据框还有很多其他的列需要保留,不仅仅是'a 或b' 的更多选择,以及其中几种类型的列要生成,所以我宁愿不使用基本的ifelse可能适用于上述基本示例的解决方案。

非常感谢您的帮助。

最佳答案

我想我现在找到了一个正确矢量化的一个类轮,在这种情况下,这也比其他答案快。

petesFun2 使用 data.table 聚合作为 petesFun,但是现在跨 column_choice 进行矢量化(而不是像以前那样按项目进行)。

虽然 petesFun2 对我来说很好,但它确实以不同的顺序保留了行和列。因此,为了与其他答案进行比较,我添加了 petesFun2Clean,它与其他答案保持相同的顺序。

petesFun2 <-function(myDat) {
  return(myDat[, cbind(.SD, chosen=.SD[[paste0(.BY$column_choice, "_data")]]),
               by=column_choice])
}

petesFun2Clean <-function(myDat) {
  myDat = copy(myDat) # To prevent reference issues
  myDat[, id := seq_len(nrow(myDat))] # Assign an id
  result = myDat[, cbind(.SD, chosen=.SD[[.BY$choice]]),
                 by=list(column_choice, choice=paste0(column_choice, "_data"))]

  # recover ordering and column order.
  return(result[order(id), 
                list(a_data, b_data, c_data, column_choice, chosen)]) 
}

benchmark(benRes<-   myFun(test.dat),
          petesRes<- petesFun(test.dat),
          dowleRes<- dowleFun(test.dat),
          petesRes2<-petesFun2(test.dat),
          petesRes2Clean<- petesFun2Clean(test.dat),
          replications=25,
          columns=c("test", "replications", "elapsed", "relative"))

#                                         test replications elapsed  relative
# 1                  benRes <- myFun(test.dat)           25   0.337  4.160494
# 3             dowleRes <- dowleFun(test.dat)           25   0.191  2.358025
# 5 petesRes2Clean <- petesFun2Clean(test.dat)           25   0.122  1.506173
# 4           petesRes2 <- petesFun2(test.dat)           25   0.081  1.000000
# 2             petesRes <- petesFun(test.dat)           25   4.018 49.604938

identical(petesRes2, benRes)
# FALSE (due to row and column ordering)
identical(petesRes2Clean, benRes)
# TRUE

编辑:我刚刚注意到(正如马修在评论中提到的)我们现在按组:=。所以我们可以删除 cbind 并简单地执行以下操作:

myDat[, 选择 := .SD[[paste0(.BY$column_choice, "_data")]],
by=column_choice]

关于r - 根据另一列的文本,整理 data.table 每行不同列的数据,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10176050/

相关文章:

r - 在 data.table 列中分割文本字符串

r - 使用 Deriv 包求导 wrt 向量

r - 使用 knit_expand() 从模板中提取 R 代码

r - 如何使用data.table在日期范围内执行联接?

r - 根据类似名称的列中的值将值赋予新列

使用rollends滚动数据表

r - fread 从大文件中读取前 n 行

r - R 2.15 的 StatEt

r - 循环遍历矩阵的对角线+1

R - 两个 data.tables 的匹配值的索引