使用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
我认为前者在某种程度上会更加惯用?任何更好的建议。
答案 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)
,则代码将失败。