【问题标题】:How to select a part of formula in formula in R?如何在R中的公式中选择公式的一部分?
【发布时间】:2012-04-19 09:00:17
【问题描述】:

假设我有以下公式:

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)

【问题讨论】:

    标签: r parsing formula


    【解决方案1】:

    不确定这是最好的,但您可以这样做:

    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)
    

    【讨论】:

    • 非常接近我想要的。解析公式很有趣,但很高兴有人帮我解析它们:)
    • 我想知道:也许有一种方法可以将 f 的定义作为字符串对象返回,即 fname &lt;- "formula(y~myfun(stuff)+z)" 。然后,您可以为 "~" 和 ")" 之间的所有内容执行 grep
    • @CarlWitthoft,我也需要括号中的内容。在我看来,将公式转换为字符串并使用 grep 并不是一个好主意。
    【解决方案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 以将其嵌套在命名函数中。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-08-31
      • 2021-03-14
      • 2023-02-05
      • 1970-01-01
      • 1970-01-01
      • 2021-10-19
      相关资源
      最近更新 更多