r语言 - 循环访问不同的列名以条件数据表中的行



下面是一个已缩小的示例。 我正在寻找一个纠正以下语法的答案,而不是"变通方法"。

set.seed(1)
dt = data.table(sum1=rnorm(10,0,1),sum2=rnorm(10,2,1))
catsummax = c(0,3)

df
      sum1       sum2
 1: -0.6264538  3.5117812
 2:  0.1836433  2.3898432
 3: -0.8356286  1.3787594
 4:  1.5952808 -0.2146999
 5:  0.3295078  3.1249309
 6: -0.8204684  1.9550664
 7:  0.4874291  1.9838097
 8:  0.7383247  2.9438362
 9:  0.5757814  2.8212212
10: -0.3053884  2.5939013

for(i in 1:2){
    dt=dt[paste0('sum',i)<=catsummax[i]]
}

这删除了所有内容,因为数据表讨厌语法。

这只保留第一列中<=第一个cat sum元素的行,然后,只保留也满足第二列的cat max的行,所以它应该给出:

df
          sum1       sum2
 3: -0.8356286  1.3787594
 6: -0.8204684  1.9550664
10: -0.3053884  2.5939013

我们可以使用Map进行相应的比较,并将其Reduce为单个逻辑vector,用于对行进行子集化

dt[, .SD[Reduce(`&`,  Map(`<=`, .SD, catsummax))]]

dt[dt[, .I[Reduce(`&`,  Map(`<=`, .SD, catsummax))]]]
#         sum1     sum2
#1: -0.8356286 1.378759
#2: -0.8204684 1.955066
#3: -0.3053884 2.593901

更新

如果数据集中还有其他列,请在.SDcols中指定感兴趣的列

dt[, .SD[Reduce(`&`,  Map(`<=`, .SD, catsummax)), .SDcols = sum1:sum2]]

您只需要在 R 中为数据表正确调用对象。数据表有点像对象的集合。要使用字符串调用它们,我们使用 get 函数。get函数基本上只是使用字符串按对象名称获取数据表条目。数据表通常使用不带引号的字符串来执行此操作。

对于您的确切代码,只需使用

for(i in 1:2){
  dt=dt[get(paste0('sum',i))<=catsummax[i],]
}

它会像魅力一样工作。

是的,明白了,尽管我不太了解整个元编程的东西,如调用、名称、表达式、替换、解析、解解析、评估、引用、引用

i <- paste(paste0("sum", 1:2, " <= ", catsummax), collapse=" & ")
dt[eval(parse(text=i))]

灵感来自:R data.table join:连接表中的 SQL"选择 *"类似语法?

为了完整起见,还有一种使用non-equi join的替代方法:

as.data.table(as.list(catsummax))[dt, on = .(V1 >= sum1, V2 >= sum2), nomatch = 0L]
           V1       V2
1: -0.8356286 1.378759
2: -0.8204684 1.955066
3: -0.3053884 2.593901

on参数也可以指定为字符向量,即

as.data.table(as.list(catsummax))[dt, on = c("V1>=sum1", "V2>=sum2"), nomatch = 0L]

这允许更灵活的编程解决方案:

如果catsummax被指定为data.table而不是与dt中的列名相同的向量进行比较,例如,

catsummax_DT <- data.table(sum1 = 0, sum2 = 3)
   sum1 sum2
1:    0    3

可以创建一个灵活的解决方案,该解决方案适用于任意和可选的列集:

library(magrittr)
cond <- names(catsummax_DT) %>% sprintf("%s>=%s", ., .)
catsummax_DT[dt, on = cond, nomatch = 0L]
         sum1     sum2
1: -0.8356286 1.378759
2: -0.8204684 1.955066
3: -0.3053884 2.593901

(magrittr只是为了方便和简洁而使用(

最新更新