Given this formula…
fixed = y ~ x1 + x2 + x3 + z1 + x3:z1We can extract all the terms as bare expressions (I prefer this to using
attr(terms(fixed), "term.labels") because the latter returns a
character vector, and I prefer to stick to manipulating unevaluated
expressions rather than parsing / unparsing — too much room for corner
cases):
get_terms = function(x) {
if (length(x) > 1 && x[[1]] == quote(`+`)) c(get_terms(x[[2]]), get_terms(x[[3]]))
else x
}
terms = get_terms(fixed[[3]])
terms## [[1]]
## x1
##
## [[2]]
## x2
##
## [[3]]
## x3
##
## [[4]]
## z1
##
## [[5]]
## x3:z1
Then we’ll build a matrix where rows are combinations and columns indicate if each term is present in that combination:
term_logicals = rep(list(c(TRUE, FALSE)), length(terms))
is_term_present = as.matrix(expand.grid(term_logicals))
is_term_present## Var1 Var2 Var3 Var4 Var5
## [1,] TRUE TRUE TRUE TRUE TRUE
## [2,] FALSE TRUE TRUE TRUE TRUE
## [3,] TRUE FALSE TRUE TRUE TRUE
## [4,] FALSE FALSE TRUE TRUE TRUE
## [5,] TRUE TRUE FALSE TRUE TRUE
## [6,] FALSE TRUE FALSE TRUE TRUE
## [7,] TRUE FALSE FALSE TRUE TRUE
## [8,] FALSE FALSE FALSE TRUE TRUE
## [9,] TRUE TRUE TRUE FALSE TRUE
## [10,] FALSE TRUE TRUE FALSE TRUE
## [11,] TRUE FALSE TRUE FALSE TRUE
## [12,] FALSE FALSE TRUE FALSE TRUE
## [13,] TRUE TRUE FALSE FALSE TRUE
## [14,] FALSE TRUE FALSE FALSE TRUE
## [15,] TRUE FALSE FALSE FALSE TRUE
## [16,] FALSE FALSE FALSE FALSE TRUE
## [17,] TRUE TRUE TRUE TRUE FALSE
## [18,] FALSE TRUE TRUE TRUE FALSE
## [19,] TRUE FALSE TRUE TRUE FALSE
## [20,] FALSE FALSE TRUE TRUE FALSE
## [21,] TRUE TRUE FALSE TRUE FALSE
## [22,] FALSE TRUE FALSE TRUE FALSE
## [23,] TRUE FALSE FALSE TRUE FALSE
## [24,] FALSE FALSE FALSE TRUE FALSE
## [25,] TRUE TRUE TRUE FALSE FALSE
## [26,] FALSE TRUE TRUE FALSE FALSE
## [27,] TRUE FALSE TRUE FALSE FALSE
## [28,] FALSE FALSE TRUE FALSE FALSE
## [29,] TRUE TRUE FALSE FALSE FALSE
## [30,] FALSE TRUE FALSE FALSE FALSE
## [31,] TRUE FALSE FALSE FALSE FALSE
## [32,] FALSE FALSE FALSE FALSE FALSE
Then we’ll get the corresponding terms and stick them together to create the right-hand side of each formula:
combinations = apply(is_term_present, 1, \(i) terms[i])
rhs = lapply(combinations, \(l) Reduce(\(x, y) bquote(.(x) + .(y)), l))
rhs## [[1]]
## x1 + x2 + x3 + z1 + x3:z1
##
## [[2]]
## x2 + x3 + z1 + x3:z1
##
## [[3]]
## x1 + x3 + z1 + x3:z1
##
## [[4]]
## x3 + z1 + x3:z1
##
## [[5]]
## x1 + x2 + z1 + x3:z1
##
## [[6]]
## x2 + z1 + x3:z1
##
## [[7]]
## x1 + z1 + x3:z1
##
## [[8]]
## z1 + x3:z1
##
## [[9]]
## x1 + x2 + x3 + x3:z1
##
## [[10]]
## x2 + x3 + x3:z1
##
## [[11]]
## x1 + x3 + x3:z1
##
## [[12]]
## x3 + x3:z1
##
## [[13]]
## x1 + x2 + x3:z1
##
## [[14]]
## x2 + x3:z1
##
## [[15]]
## x1 + x3:z1
##
## [[16]]
## x3:z1
##
## [[17]]
## x1 + x2 + x3 + z1
##
## [[18]]
## x2 + x3 + z1
##
## [[19]]
## x1 + x3 + z1
##
## [[20]]
## x3 + z1
##
## [[21]]
## x1 + x2 + z1
##
## [[22]]
## x2 + z1
##
## [[23]]
## x1 + z1
##
## [[24]]
## z1
##
## [[25]]
## x1 + x2 + x3
##
## [[26]]
## x2 + x3
##
## [[27]]
## x1 + x3
##
## [[28]]
## x3
##
## [[29]]
## x1 + x2
##
## [[30]]
## x2
##
## [[31]]
## x1
##
## [[32]]
## NULL
Formulas would then be something like:
lapply(rhs, \(r) bquote(y ~ .(r)))## [[1]]
## y ~ x1 + x2 + x3 + z1 + x3:z1
##
## [[2]]
## y ~ x2 + x3 + z1 + x3:z1
##
## [[3]]
## y ~ x1 + x3 + z1 + x3:z1
##
## [[4]]
## y ~ x3 + z1 + x3:z1
##
## [[5]]
## y ~ x1 + x2 + z1 + x3:z1
##
## [[6]]
## y ~ x2 + z1 + x3:z1
##
## [[7]]
## y ~ x1 + z1 + x3:z1
##
## [[8]]
## y ~ z1 + x3:z1
##
## [[9]]
## y ~ x1 + x2 + x3 + x3:z1
##
## [[10]]
## y ~ x2 + x3 + x3:z1
##
## [[11]]
## y ~ x1 + x3 + x3:z1
##
## [[12]]
## y ~ x3 + x3:z1
##
## [[13]]
## y ~ x1 + x2 + x3:z1
##
## [[14]]
## y ~ x2 + x3:z1
##
## [[15]]
## y ~ x1 + x3:z1
##
## [[16]]
## y ~ x3:z1
##
## [[17]]
## y ~ x1 + x2 + x3 + z1
##
## [[18]]
## y ~ x2 + x3 + z1
##
## [[19]]
## y ~ x1 + x3 + z1
##
## [[20]]
## y ~ x3 + z1
##
## [[21]]
## y ~ x1 + x2 + z1
##
## [[22]]
## y ~ x2 + z1
##
## [[23]]
## y ~ x1 + z1
##
## [[24]]
## y ~ z1
##
## [[25]]
## y ~ x1 + x2 + x3
##
## [[26]]
## y ~ x2 + x3
##
## [[27]]
## y ~ x1 + x3
##
## [[28]]
## y ~ x3
##
## [[29]]
## y ~ x1 + x2
##
## [[30]]
## y ~ x2
##
## [[31]]
## y ~ x1
##
## [[32]]
## y ~ NULL