循环使用不同的列名来调整数据表

时间:2018-04-11 05:14:57

标签: r data.table rows

以下是已按比例缩小的示例。我正在寻找一个能够纠正以下语法的答案,而不是“解决方法”。

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]]
}

这会丢弃所有内容,因为数据表讨厌语法。

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

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

4 个答案:

答案 0 :(得分:2)

我们可以使用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]]

答案 1 :(得分:1)

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

要获得确切的代码,请使用

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

它会像魅力一样发挥作用。

答案 2 :(得分:0)

是的,得到它虽然我不太了解整个元编程的东西,如call,name,expression,substitute,parse,deparse,eval,quote,enquote

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

灵感来自: R data.table join: SQL "select *" alike syntax in joined tables?

答案 3 :(得分:0)

为了完整起见,还有一种使用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仅用于方便和简洁)