设置'i'条件作为参数传递

时间:2014-06-05 23:33:26

标签: r data.table

我试图创建一个函数,它将data.table和condition作为输入,然后修改由条件选择的行。当然,我可以明确地将条件定义为逻辑向量,如下所示:

dt1 <- fread(
       "id,a,b
       id1,1,10
       id2,2,30
       id3,3,40
     ")

test1 <- function(dtIn, condition) {
 dtIn[condition, newcol:="new text"];
 return(dtIn);
}    

test1(dt1, dt1$b>10);

但理想情况下,我希望能够在没有表名的情况下通过这个条件,如下所示:

test2 <- function(dtIn, condition) {
 dtIn[substitute(condition), newcol:="new text"];
 return(dtIn);
}

test2(dt1, b>10);

我尝试了substitute(condition),但是它出现错误&#34; i has not evaluated to logical, integer or double&#34;。是否可以实现所需的功能?


UPD。 正如@Gregor所回答的那样,除了eval之外,正确的代码只使用了substitute

test3 <- function(dtIn, condition) {
  dtIn[eval(substitute(condition)), newcol:="new text"];
  return(dtIn);
}

我还需要传递列名并在我的函数中构建条件。根据@Gregor的建议,我可以paste建立条件,然后使用eval(parse(...))

test4p <- function(dtIn, colName) {
  condition <- parse(text=paste0(colName, ">20"))
  dtIn[eval(condition), newcol:="new text"];
  return(dtIn);
}

test4p(dt1, "b");

我自己,我采用另一种方法,使用get

test4g <- function(dtIn, colName) {
  dtIn[get(colName)>20, newcol:="new text"];
  return(dtIn);
}

test4g(dt1, "b");

结果是一样的,我没有足够的能力来解释geteval(parse(...))的使用之间的区别,所以欢迎您提出意见。 使用eval(parse(...)),我能够使函数采用不带引号的列名,即用于调用test4(dt1, b)(只是将substitute(colName)添加到代码中),但是没有{{1 }}

1 个答案:

答案 0 :(得分:3)

您只是错过了eval()

test3 <- function(dtIn, condition) {
 dtIn[eval(substitute(condition)), newcol:="new text"];
 return(dtIn);
}

> test3(dt1, dt1$b>10);
           id a  b   newcol
1:        id1 1 10       NA
2:        id2 2 30 new text
3:        id3 3 40 new text

即使没有dt1$

也能正常工作
> test3(dt1, b>10);
           id a  b   newcol
1:        id1 1 10       NA
2:        id2 2 30 new text
3:        id3 3 40 new text

有关详细说明,请参阅Hadley's Non-Standard Evaluation Section