【问题标题】:Editing data.table column in place based on row numbers within conditional subset根据条件子集中的行号编辑 data.table 列
【发布时间】:2019-01-13 17:27:50
【问题描述】:

使用 mtcar 数据集进行演示。

我正在根据一些模型输出在 data.table 中标记潜在的异常值,并希望根据条件子集中的行号(下面的“outliernums”,我的异常值检测函数的输出)增加一个“regflag”列(圆柱 == 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 

我认为前者会更惯用吗?有什么更好的推荐。

【问题讨论】:

  • 您在寻找更快的方法吗?更好的方法?我不清楚您的预期输出。
  • 我正在寻找速度,而实际问题看起来确实像这个问题,那么subsetmethod 是最有效的。但是如果你想同样对待所有cyl,也许你应该改变outliernums的格式
  • @NelsonGon 是的,更快会很棒,但它也感觉很笨重,所以我想知道是否有一些更优雅/惯用的东西我错过了。
  • 您能否添加显示异常值删除或红旗的示例输出以更好地遵循逻辑。
  • @NelsonGon 我如何得到异常值的细节不一定是问题的一部分(即 setDT(ols_plot_resid_lev(model)$plot$data)[color %in% c('outlier ', '异常值和杠杆'), obs] 其中模型是 lm 模型的输出,library(olsrr))。我想弄清楚的是,有没有一种更快/更优雅的方法来编辑这个 data.table 为基于 cyl==6 的子集中编号行的子集。

标签: r data.table


【解决方案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

与 cmets 一样,我没有看到明显的应用程序,如果 which(cyl == 6) 小于 max(outliernums),代码将失败。

【讨论】:

  • 太好了,谢谢!就我而言,根据定义, max(outliernums) 不能超过它,因为异常行数首先来自该子集。为了简单起见,我在这里依赖 mtcar 数据集。在应用方面,我只是在运行工具,将每个子集的异常值指出为 for 循环中的行号,因此肯定有一个应用程序 :)
猜你喜欢
  • 2021-10-04
  • 2017-01-18
  • 1970-01-01
  • 2021-06-01
  • 1970-01-01
  • 2014-08-03
  • 1970-01-01
  • 1970-01-01
  • 2020-03-30
相关资源
最近更新 更多