Подтвердить что ты не робот

Есть ли более эффективная альтернатива, чем манипулирование строками для программной сборки формул?

Все остальные функции, похоже, принимают объекты формулы, а затем делают темную магию к ним где-то глубоко внутри, и я ревную.

Я пишу функцию, которая подходит для нескольких моделей. Части формул для этих моделей остаются неизменными и частично меняются от одной модели к другой. Неуклюжим способом было бы заставить пользователя вводить части формулы в виде символьных строк, выполнять некоторые манипуляции с ними, а затем использовать 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

... но, к сожалению, ни один синтаксис не работает. Кто-нибудь знает, есть ли что-то, что делает? Спасибо.

4b9b3361

Ответ 1

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.formula с помощью . разумно

 update(~a+b, y ~ .)
 ##  y~a+b