jslefche
jslefche

Reputation: 4599

How to drop terms from a mixed model formula

I have a rather specific regular expressions problem that is causing me some grief. I have removed one or more fixed effects from a mixed model (either lme or lme4), and wish to remove the corresponding random slope(s). However, depending on the random structure, this may leave behind unnecessary + symbols or, worse, leave nothing preceding the |.

Take a list of random effects formulae from lme and lme4 obtained using lme.model$call$random and findbars(formula(lme4.model)) respectively:

   random.structures = list(
  "~ b | random1",
  "(b | random1)",
  "~ b + x1 | random1",
  "(b + x1 | random1)",
  "~ x1 + b| random1",
  "(x1 + b| random1)",
  "~ b + x1 + c | random1",
  "(b+ x1 + c | random1)",
  "~b + x1 + x2 | random1",
  "(b + x1 + x2 | random1)",
  "~ x1 + x2 + b | random1",
  "(x1 + x2 + b | random1)"
)

I have removed the variables b and c from the fixed effects formula using dropterms. Since they no longer exist as fixed effects, their random slopes should not be allowed to vary.

b and c can be removed from the random formulae above using the following line:

random.structures = lapply(random.structures, function(i) gsub("b|c", "", i))

Now, I wish to remove all leftover + symbols, i.e., those that do not link variables.

Then, in the event there is a blank space between ~ or ( and |, I wish to insert a 1.

The desired output is

random.structures2 = list(
  "~ 1 | random1",
  "(1 | random1)",
  "~ x1 | random1",
  "(x1 | random1)",
  "~ x1 | random1",
  "(x1 | random1)",
  "~ x1 | random1",
  "(x1 | random1)",
  "~ x1 + x2 | random1",
  "(x1 + x2 | random1)",
  "~ x1 + x2 | random1",
  "(x1 + x2 | random1)"
)

I have fiddled with gsub but just can't seem to get it right. For instance, this works:

gsub("(.*)\\+\\ |(.*)\\+(\\|)", "\\1", random.structures[[3]])
# Accounting for space or lack of space between + and |

But not for this:

gsub("(.*)\\+\\ |(.*)\\+(\\|)", "\\1", random.structures[[7]])

Alternately, if there is a preexisting function like dropterms for random structures, I'm all in!

Similarly, I can't reliable insert a 1 in the blank space inbetween ~ | or ( |.

Upvotes: 1

Views: 1192

Answers (1)

MrFlick
MrFlick

Reputation: 206243

Half the items in your starting list are proper formulas (the ones with the "~"). I'm not sure what you are doing with the terms in the parenthesis. But for the formulas, you can use the Formula package for better support for dropping terms with conditioning terms.

Here I'll subset to the proper formulas and convert to Formula objects.

library(Formula)
rx <- lapply(random.structures[grep("~", random.structures)],
    function(x) Formula(as.formula(x)))

We can quickly peak at the results with

sapply(rx, deparse)

# [1] "~b | random1"
# [2] "~b + x1 | random1"
# [3] "~x1 + b | random1"
# [4] "~b + x1 + c | random1"
# [5] "~b + x1 + x2 | random1"
# [6] "~x1 + x2 + b | random1"

Now we can remove b and c from all of these with

nx <- lapply(x, function(x) update(x, ~.-b-c))

and view the results with

sapply(nx, deparse)

# [1] "~1 | random1" 
# [2] "~x1 | random1"
# [3] "~x1 | random1"
# [4] "~x1 | random1"
# [5] "~x1 + x2 | random1"
# [6] "~x1 + x2 | random1"

You should have no problem using these where ever you would use regular formulas.

Upvotes: 3

Related Questions