2012-04-19 67 views
5

假设我有一个下面的公式:如何选择R中公式中的一部分公式?

fr <- formula(y~myfun(x)+z) 

鉴于对象fr是有R中的函数返回myfun(x)?我写了自己的函数(代码如下),它基本上做我需要的,但也许有一些标准的方法来做到这一点?

我的函数的代码:

selectmds <- function(expr,funcn) { 
    if(length(expr)>2) { 
     a <- expr[[2]] 
     b <- expr[[3]] 
     if(length(a)>1) { 
      if(as.name(a[[1]])==funcn) { 
       if(length(grep(funcn,all.names(b)))>0) { 
        return(list(a,selectmds(b,funcn))) 
       } 
       else return(list(a)) 
      } 
     } 
     if(length(b)>1) { 
      if(as.name(b[[1]])==funcn) { 
       if(length(grep(funcn,all.names(a)))>0) { 
        return(list(b,selectmds(a,funcn))) 
       } 
       else return(list(b)) 
      } 
     } 
     for(i in 2:length(expr)) { 
      if(length(grep(funcn,all.names(expr[[i]])))>0)return(selectmds(expr[[i]],funcn)) 
     } 
    } 
    return(NULL) 
} 

下面是几个例子:

> selectmds(formula(y~myfun(x)+z),"myfun") 
[[1]] 
myfun(x) 


> unlist(selectmds(formula(y~myfun(x)+z+myfun(zz)),"myfun")) 
[[1]] 
myfun(zz) 

[[2]] 
myfun(x) 

回答

7

不知道这是最好的,但你可以做到这一点:

f <- function(fm, fun) { 
    l <- as.list(attr(terms(fm), "variables"))[-1] 
    l[grep(fun, l)] 
} 

然后,

> f(formula(y~myfun(x)+z),"myfun") 
[[1]] 
myfun(x) 

> f(formula(y~myfun(x)+z+myfun(zz)),"myfun") 
[[1]] 
myfun(x) 

[[2]] 
myfun(zz) 
+0

非常接近我寻找的东西。解析公式很有趣,但是有人可以为我解析:) – mpiktas 2012-04-19 09:27:46

+0

我想知道:也许有一种方法可以将'f'的定义作为字符串对象返回,即'fname < - “formula(y 〜myfun(stuff)+ z)“'。然后,您可以对“〜”和“)”之间的所有内容执行'grep'。 – 2012-04-19 14:57:00

+0

@CarlWitthoft,我也需要括号中的东西。在我看来,将公式转换为字符串并使用grep并不是一个好主意。 – mpiktas 2012-04-19 17:06:06

2

terms有一个specials参数,它允许您在公式中标记命名函数以按位置提取。

所以,你可以写

selectmds<-function(form,fn) { 
    tt<-terms(form,specials=fn); 
    idx<-attr(tt,"specials"); 
    v<-as.list(attr(tt,"variables"))[-1]; 
    unlist(lapply(idx,function(i) v[i])) 
} 

那么你的测试用例给

> selectmds(formula(y~myfun(x)+z),"myfun") 
$myfun 
myfun(x) 

> selectmds(formula(y~myfun(x)+z+myfun(zz)),"myfun") 
$myfun1 
myfun(x) 

$myfun2 
myfun(zz) 

但是,你也可以做

> selectmds(formula(y~myfun(x)+myfun(x2)+z+yourfun(zz)),c("myfun","yourfun")) 
$myfun1 
myfun(x) 

$myfun2 
myfun(x2) 

$yourfun 
yourfun(zz) 

在那里你可以罢工的unlist有此嵌套由命名函数代替。