由列条件子集和data.table

时间:2019-07-04 17:54:34

标签: r data.table

@gented的答案here演示了如何从data.table中随机选择行的子集。

如果我想选择data.table中某个列中的值满足特定条件的所有行,并且另外从data.table中选择一个行的随机子集作为值,该怎么办?在同一列中满足不同条件?

举例来说,我想从mtcars data.table中随机抽取5行样本,其中cyl == 6的所有行均{ {1}}。

这是比以下方法更好的实现吗?

cyl == 8

也就是说,我可以将rbind( mtcars[ cyl == 8 ], mtcars[ cyl == 6 ][ sample(.N, 5) ] ) 包含在一组data.table中吗?例如,我还可以在该调用中应用一个函数(在[]中格式)?

这显然不能达到预期的结果,但是与我正在寻找的语法类似:

lapply(.SD, function)

2 个答案:

答案 0 :(得分:1)

只要i的结尾可以用来选择行, 您可以在其中放置任何有效的表达式, 从技术上讲,这意味着您可以编写:

DT[c(sample(which(cyl == 6), 5L), which(cyl == 8))]

但这可能不会从optimizations中受益。

基于this answer (和secondary indices), 我认为这样会更快:

sample_if <- function(condition, values, n) {
  if (condition)
    sample(values, n)
  else
    values
}

some_fun <- function(.SD) {
  .SD
}

DT[DT[.(c(6, 8)), sample_if(.BY$cyl == 6, .I, 5L), by = "cyl", on = "cyl"]$V1,
   some_fun(.SD),
   .SDcols = c("cyl", "mpg")]
    cyl  mpg
 1:   6 19.7
 2:   6 19.2
 3:   6 21.4
 4:   6 21.0
 5:   6 18.1
 6:   8 18.7
 7:   8 14.3
 8:   8 16.4
 9:   8 17.3
10:   8 15.2
11:   8 10.4
12:   8 10.4
13:   8 14.7
14:   8 15.5
15:   8 15.2
16:   8 13.3
17:   8 19.2
18:   8 15.8
19:   8 15.0

答案 1 :(得分:1)

为此,我将使用.I特殊符号,如下所示:

DT <- as.data.table(mtcars)

DT[c(DT[, .I[cyl == 8]], sample(DT[, .I[cyl == 6]], 5))]

现在您可以进行一些计算:

set.seed(2019)
DT[c(DT[, .I[cyl == 8]], sample(DT[, .I[cyl == 6]], 5))
   , lapply(.SD, mean)
   , by = am
   , .SDcols = 3:5]

给出:

   am   disp       hp     drat
1:  0 325.64 179.0667 3.224667
2:  1 243.00 204.7500 3.890000

如果您想在以后重用该索引向量,可以预先存储它:

idx <- c(DT[, .I[cyl == 8]], sample(DT[, .I[cyl == 6]], 5))

DT[idx, lapply(.SD, mean), .SDcols = 3:5]