2
  • 编辑:我为同样的情况做了一个更简单的例子:

    我试图fn从模型公式中删除与函数相对应的一项。

    f<-formula(y~x+fn(z=1))
    update(f,.~.-fn(z=1)) #remove the last term
    y ~ x 
    
    rm(a)
    f<-formula(y~x+fn(z=a))
    update(f,.~.-fn(z=a)) #works
    y ~ x
    
    #even these work:
    f<-formula(y~x+fn(z=a));update(f,.~.-fn(z=a))
    f<-formula(y~x+fn(a));update(f,.~.-fn(z=a))
    f<-formula(y~x+fn(z=a));update(f,.~.-fn(a))
    
    f<-formula(y~x+fn(z=NA))
    update(f,.~.-fn(z=NA)) #does not work
    y ~ x + fn(z = NA)
    
    #Probably something to do with environments, as these do not work:
    update(formula(y~x+fn(z=a)),.~.-fn(z=a)) #works
    y ~ x
    > update(formula(y~x+fn(z)),.~.-fn(z=a)) #nope
    y ~ x + fn(z)
    > update(formula(y~x+fn(z=a)),.~.-fn(z)) #this neither
    y ~ x + fn(z = a)
    

    所以formula.update(或terms.formula)中发生了一些我不明白的事情。


  • 旧位;更复杂的例子和一些挖掘里面formula.update

    我试图弄清楚如何更新formula对象,以便我可以删除一些与稍后将使用的函数相关的特殊变量。

    这是一个简单的例子:

    f<-formula(y~x+fn(z=1))
    vars<-terms(f, c("fn"))
    rmterm<-attr(vars, "variables")[[1 + attr(vars, "specials")$fn]]   
    rmterm
    fn(z = 1)
    update(f, paste(".~.-", deparse(rmterm, width.cutoff = 500L, backtick = TRUE)))
    y ~ x
    

    到目前为止,一切都按预期工作。但是,如果我NA用作该术语的参数,fn则不会删除:

    f<-formula(y~x+fn(z=NA))
    vars<-terms(f, c("fn"))
    rmterm<-attr(vars, "variables")[[1 + attr(vars, "specials")$fn]]   
    rmterm
    fn(z = NA)
    
    update(f, paste(".~.-", deparse(rmterm, width.cutoff = 500L, backtick = TRUE)))
    y ~ x + fn(z = NA)   
    

    我想出了一种解决方案来避免这种情况,但是感觉很hacky并且很难概括,因为公式中可以有几个函数包含一个NA参数和一些非NA参数:

    rmterm[[2]][[1]]<-1
    f[[3]][[3]][[2]]<-1
    f<-update(f,paste(".~.-",deparse(rmterm, width.cutoff = 500L, backtick = TRUE)))
    f
    y ~ x
    rmterm[[2]][[1]]<-NA #I need the NA back
    rmterm ## NA becomes NA_real, which probably doesn't matter
    fn(z = NA_real_) 
    

    所以我的问题是为什么不update.formula使用NA's,以及解决这个问题的好方法是什么?


  • 编辑:查看update.formula函数内部:

    update.formula
    function (old, new, ...) 
    {
        tmp <- .Internal(update.formula(as.formula(old), as.formula(new)))
        out <- formula(terms.formula(tmp, simplify = TRUE))
        return(out)
    }
    
    • 输出.Internal

      f<-formula(y~x+fn(z = NA))
      vars<-terms(f, c("fn"))
      rmterm<-attr(vars, "variables")[[1 + attr(vars, "specials")$fn]]   
      old<-f
      new<-paste(". ~ .-", deparse(rmterm, width.cutoff = 500L, backtick = TRUE))
      tmp <- .Internal(update.formula(as.formula(old), as.formula(new)))
      
      tmp
      y ~ (x + fn(z = NA)) - fn(z = NA)
      attr(,".Environment")
      <environment: R_GlobalEnv>
      
    • 看起来不错。然后输出terms.formula

      terms.formula(tmp, simplify = TRUE)
      y ~ x + fn(z = NA)
      attr(,"variables")
      list(y, x, fn(z = NA), fn(z = NA))
      attr(,"factors")
                 x fn(z = NA)
      y          0          0
      x          1          0
      fn(z = NA) 0          1
      fn(z = NA) 0          0
      attr(,"term.labels")
      [1] "x"          "fn(z = NA)"
      attr(,"order")
      [1] 1 1
      attr(,"intercept")
      [1] 1
      attr(,"response")
      [1] 1
      attr(,".Environment")
      <environment: R_GlobalEnv>
      
    • 这是不正确的。为了比较,这里是使用时相同的输出fn(z=1)

      tmp
      y ~ (x + fn(z = 1)) - fn(z = 1)
      attr(,".Environment")
      <environment: R_GlobalEnv>
      
      terms.formula(tmp, simplify = TRUE)
      y ~ x
      attr(,"variables")
      list(y, x, fn(z = 1))
      attr(,"factors")
                x
      y         0
      x         1
      fn(z = 1) 0
      attr(,"term.labels")
      [1] "x"
      attr(,"order")
      [1] 1
      attr(,"intercept")
      [1] 1
      attr(,"response")
      [1] 1
      attr(,".Environment")
      <environment: R_GlobalEnv>
      

    所以看来问题出在内部terms.formula函数的某个地方。

4

0 回答 0