创建标志,指示年变量是否在data.table中的start:end变量范围内

Luc*_*ion 6 r data.table

我有3个日期变量data.table: ,year,。startend

test <- data.table(year=2001:2003,start=c(2003,2002,2000),end=c(2003,2004,2002),x_desired=c(F,T,F))
Run Code Online (Sandbox Code Playgroud)

Ò希望创建一个新的变量x,指示,对于每一行,如果year是在所规定的范围startend。正确的期望结果在变量中x_desired

我以为可以做到这一点:

test[,x:=(year %in% start:end)]
Run Code Online (Sandbox Code Playgroud)

但是结果显然是不正确的。我想逐行定义范围,但不知道如何表达。

Wim*_*pel 6

另一种方法

#first, create a x-column with all FALSE
DT[, x := FALSE ]
#update the x-column subset where year is between start and end to TRUE
DT[ year %between% list(start,end), x := TRUE] 
Run Code Online (Sandbox Code Playgroud)

应该跑得快...基准很快就会跟进

更新:在1M行的data.table上的基准测试

n = 1000000
set.seed(123)
dt <- data.table(year =sample( 2001:2003, n, replace = TRUE),
                 start=sample( c(2003,2002,2000), n, replace = TRUE),
                 end  =sample( c(2003,2004,2002), n, replace = TRUE) )

microbenchmark::microbenchmark( 
  wimpel = {
    DT <- copy(dt) 
    DT[, x := FALSE ]
    DT[ year %between% list(start,end), x := TRUE] 
    },
  akrun_nrow = {
    DT <- copy(dt)
    DT[, x := between(year, start, end), 1:nrow(DT)]
    },
  akrun_map = {
    DT <- copy(dt)
    DT[, x := unlist(do.call(Map, c(f = between, unname(.SD)))), .SDcols = year:end]
    },
  akrun_pmap = {
    DT <- copy(dt)
    DT[, x := purrr::pmap_lgl(.SD[, .(x = year, left = start, right = end)], between)]
    },
  markus = {
    DT <- copy(dt)
    DT[, col := mapply(between, year, start, end)]
  },
  times = 3
  )
Run Code Online (Sandbox Code Playgroud)

结果

Unit: milliseconds
       expr        min         lq       mean     median         uq        max neval
     wimpel   29.98388   30.41861   48.98399   30.85333   58.48404   86.11475     3
 akrun_nrow 2741.35268 2755.01860 2944.58975 2768.68453 3046.20829 3323.73206     3
  akrun_map 3673.21253 3683.22849 3711.51209 3693.24446 3730.66188 3768.07929     3
 akrun_pmap 3281.13335 3291.04689 3406.46131 3300.96043 3469.12528 3637.29013     3
     markus 3408.07869 3569.33044 3670.68141 3730.58219 3801.98277 3873.38334     3
Run Code Online (Sandbox Code Playgroud)

似乎有明显的赢家..但也许我在这里错过了什么?