根据条件子集中的行号在适当位置编辑data.table列

时间:2019-01-13 17:27:51

标签: r data.table

使用mtcar数据集进行演示。

我正在基于某些模型输出在data.table中标记潜在异常值,并希望根据条件子集中的行号(以下为“异常值”,即我的异常值检测功能的输出)来增加“ regflag”列(cyl == 6)。在data.table中执行此操作的更快和/或更优雅/惯用的方式是什么?

library(data.table)
library(microbenchmark)
outliernums <- c(1,3,5)
cars <- as.data.table(mtcars)
cars[, regflags := 0]
mbm = microbenchmark(
  imethod = cars[cyl == 6, regflags := ifelse(.I %in% outliernums, regflags+1, regflags)],
  subsetmethod = cars[which(cars$cyl == 6)[outliernums], regflags := regflags +1],
  times=1000
)
mbm

输出:

Unit: microseconds
         expr      min        lq      mean    median       uq      max neval cld
      imethod 1236.603 1721.7990 3829.3193 2322.0490 6296.972 34526.04  1000   b
 subsetmethod  284.809  423.7495  938.4575  561.7775 1519.042 11189.23  1000  a 

我认为前者在某种程度上会更加惯用?任何更好的建议。

1 个答案:

答案 0 :(得分:1)

在这个小例子中,这里的解决方案要快一些

library(data.table)
library(microbenchmark)
outliernums <- c(1L, 3L, 5L)
cars <- as.data.table(mtcars)
cars[, regflags := 0L]
# gives the same
o1 <- copy(cars)
o1[
  cyl == 6, regflags := ifelse(.I %in% outliernums, regflags + 1L, regflags)]
o2 <- copy(cars)
o2[
  which(cyl == 6)[outliernums], regflags := regflags + 1L]
o3 <- copy(cars)
o3[, regflags := regflags + .I %in% which(cyl == 6)[outliernums]]
all.equal(as.data.frame(o1), as.data.frame(o2), check.attributes = FALSE)
#R [1] TRUE
all.equal(as.data.frame(o1), as.data.frame(o3), check.attributes = FALSE)
#R [1] TRUE

microbenchmark(
  `ifelse` = cars[
    cyl == 6, regflags := ifelse(.I %in% outliernums, regflags + 1L, regflags)],
  `subset method` = cars[
    which(cyl == 6)[outliernums], regflags := regflags + 1L],
  alternative = cars[
    , regflags := regflags + .I %in% which(cyl == 6)[outliernums]],
  times = 1000)
#R Unit: microseconds
#R           expr      min       lq      mean   median       uq       max neval
#R         ifelse 1863.883 1922.782 2038.1044 1939.477 1966.840 19048.795  1000
#R  subset method  482.783  498.551  526.2885  503.652  513.856  2851.244  1000
#R    alternative  279.189  320.928  337.9042  326.493  332.986  2634.665  1000

如评论中所示,我看不到明显的应用程序,如果which(cyl == 6)少于max(outliernums),则代码将失败。