53

其他人的函数似乎都采用公式对象,然后在内心深处的某个地方对它们施以黑魔法,我很嫉妒。

我正在编写一个适合多个模型的函数。这些模型的部分公式保持不变,而从一个模型到另一个模型的部分变化。笨拙的方法是让用户将公式部分输入为字符串,对其进行一些字符操作,然后使用as.formula.

但在我走这条路之前,我只是想确保我没有忽略一些更简洁的方法,它允许函数接受标准 R 格式的公式(例如,从其他使用公式的对象中提取)。

我想要类似的东西...

> LHS <- y~1; RHS <- ~a+b; c(LHS,RHS);
y ~ a + b
> RHS2 <- ~c;
> c(LHS, RHS, RHS2);
y ~ a + b + c

或者...

> LHS + RHS;
y ~ a + b
> LHS + RHS + RHS2;
y ~ a + b + c

...但不幸的是,两种语法都不起作用。有人知道是否有什么可以做的吗?谢谢。

4

1 回答 1

73

reformulate会做你想做的。

reformulate(termlabels = c('x','z'), response = 'y')
## y ~ x + z

或者没有拦截

reformulate(termlabels = c('x','z'), response = 'y', intercept = FALSE)
## y ~ x + z - 1

请注意,您不能构造具有多个公式的公式,reponses例如x+y ~z+b

reformulate(termlabels = c('x','y'), response = c('z','b'))
z ~ x + y

从现有的formula(给定您的示例)中提取术语

attr(terms(RHS), 'term.labels')
## [1] "a" "b"

得到的响应稍有不同,一种简单的方法(对于单变量响应)。

as.character(LHS)[2]
## [1] 'y'


combine_formula <- function(LHS, RHS){
  .terms <- lapply(RHS, terms)
  new_terms <- unique(unlist(lapply(.terms, attr, which = 'term.labels')))
  response <- as.character(LHS)[2]

  reformulate(new_terms, response)


}


combine_formula(LHS, list(RHS, RHS2))

## y ~ a + b + c
## <environment: 0x577fb908>

我认为将响应指定为字符向量会更明智,例如

combine_formula2 <- function(response, RHS, intercept = TRUE){
  .terms <- lapply(RHS, terms)
  new_terms <- unique(unlist(lapply(.terms, attr, which = 'term.labels')))
  response <- as.character(LHS)[2]

  reformulate(new_terms, response, intercept)


}
combine_formula2('y', list(RHS, RHS2))

您还可以定义一个+运算符来处理公式(更新为公式对象设置新方法)

`+.formula` <- function(e1,e2){
  .terms <- lapply(c(e1,e2), terms)
  reformulate(unique(unlist(lapply(.terms, attr, which = 'term.labels'))))
}

RHS + RHS2
## ~a + b + c

您也可以明智地使用update.formulausing.

 update(~a+b, y ~ .)
 ##  y~a+b
于 2012-10-19T05:22:22.290 回答