首页 > 解决方案 > 根据条件子集中的行号编辑 data.table 列

问题描述

使用 mtcar 数据集进行演示。

我正在根据一些模型输出在 data.table 中标记潜在的异常值,并希望在条件子集 (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 

我认为前者会以某种方式更惯用吗?有什么更好的推荐。

标签: rdata.table

解决方案


这是这个小例子的稍微快一点的解决方案

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).


推荐阅读