从公式中删除偏移项

Ben*_*ker 10 r formula

R有一个方便的工具来操纵公式,update.formula().当你想得到类似"包含以前公式中所有术语的公式除外x"时,这很有效,例如

f1 <- z ~ a + b + c
(f2 <- update.formula(f1, . ~ . - c))
## z ~ a + b
Run Code Online (Sandbox Code Playgroud)

但是,这似乎不适用于抵消条款:

f3 <- z ~ a + offset(b) 
update(f3, . ~ . - offset(b))
## z ~ a + offset(b)
Run Code Online (Sandbox Code Playgroud)

我已经挖了下来terms.formula,?update.formula参考:

[替换后,...]然后通过 'terms.formula(simplify = TRUE)'简化结果.

terms.formula(z ~ a + offset(b) - offset(b), simplify=TRUE)
## z ~ a + offset(b)
Run Code Online (Sandbox Code Playgroud)

(也就是说,这似乎没有删除offset(b)......)

我知道我可以通过使用deparse()和文本处理来破解解决方案,或者通过递归处理公式来删除我不想要的术语,但是这些解决方案实现起来很丑陋和/或烦人.无论是为什么这不起作用的启示,还是一个相当紧凑的解决方案,都会很棒......

G. *_*eck 7

1)递归递归下降通过公式替换offset(...),offset然后删除offset使用update.没有进行字符串操作,虽然它确实需要多行代码,但它仍然相当短,并且确实删除了单个和多个offset术语.

如果存在多个偏移,则可以通过设置来保留它们中的一些preserve,例如,如果preserve = 2那么保留第二偏移并且移除任何其他偏移.默认是保留none,即全部删除它们.

no.offset <- function(x, preserve = NULL) {
  k <- 0
  proc <- function(x) {
    if (length(x) == 1) return(x)
    if (x[[1]] == as.name("offset") && !((k<<-k+1) %in% preserve)) return(x[[1]])
    replace(x, -1, lapply(x[-1], proc))
  }
  update(proc(x), . ~ . - offset)
}

# tests

no.offset(z ~ a + offset(b))
## z ~ a

no.offset(z ~ a + offset(b) + offset(c))
## z ~ a
Run Code Online (Sandbox Code Playgroud)

请注意,如果您不需要preserve参数,则k可以省略行初始化并将其if简化为:

if (x[[1]] == as.name("offset")) return(x[[1]])
Run Code Online (Sandbox Code Playgroud)

2)术语 这既不直接使用字符串操作也不使用递归.首先获取terms对象,删除它的offset属性并使用fixFormulaObject它从我们的内容中提取它来修复它terms.formula.通过将源代码复制fixFormulaObject到源中并删除eval下面的行,可以减少这一点. preserve行为如(1).

no.offset2 <- function(x, preserve = NULL) {
  tt <- terms(x)
  attr(tt, "offset") <- if (length(preserve)) attr(tt, "offset")[preserve]
  eval(body(terms.formula)[[2]]) # extract fixFormulaObject
  f <- fixFormulaObject(tt)
  environment(f) <- environment(x)
  f
}

# tests

no.offset2(z ~ a + offset(b))
## z ~ a

no.offset2(z ~ a + offset(b) + offset(c))
## z ~ a
Run Code Online (Sandbox Code Playgroud)

请注意,如果您不需要preserve参数,那么zaps offset属性的行可以简化为:

attr(tt, "offset") <- NULL
Run Code Online (Sandbox Code Playgroud)