53 votes

Existe-t-il une meilleure alternative que la manipulation de chaînes pour créer des formules par programme?

Toutes les autres fonctions semblent prendre la formule des objets et de faire de la magie noire pour eux quelque part profondément à l'intérieur et je suis jaloux.

Je suis en train d'écrire une fonction qui s'adapte à plusieurs modèles. Les pièces des formules pour ces modèles restent les mêmes et le changement des pièces d'un modèle à l'autre. Maladroit, il faudrait disposer de la saisie de l'utilisateur de la formule de pièces comme des chaînes de caractères, faire un peu de caractère manipulation sur eux, et ensuite utiliser as.formula.

Mais avant d'aller dans cette voie, je veux juste m'assurer que je ne suis pas passer à côté des plus propre façon de faire qui permettrait à la fonction d'accepter les formules de la norme R format (par exemple un extrait d'une formule à l'aide d'objets).

Je veux quelque chose comme...

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

ou...

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

...mais malheureusement, ni la syntaxe fonctionne. Quelqu'un sait si il y a quelque chose qui le fasse? Merci.

73voto

mnel Points 48160

reformulate à faire ce que vous voulez.

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

Ou sans interception

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

Notez que vous ne pouvez pas construire des formules avec plusieurs reponses comme x+y ~z+b

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

Pour extraire les termes à partir d'un formula (compte tenu de votre exemple)

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

Pour obtenir la réponse est légèrement différente, une approche simple (pour une seule variable de réponse).

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>

Je pense qu'il serait plus judicieux de spécifier la réponse comme un personnage, vectoriel, quelque chose comme

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))

vous pouvez également définir une + à l'opérateur de travailler avec des formules (paramètre de mise à jour d'une nouvelle méthode pour la formule objets)

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

RHS + RHS2
## ~a + b + c

Vous pouvez également utiliser update.formula l'aide . judicieusement

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

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X