Найти шаблон только до первого появления другого шаблона (или: как удалить случайные эффекты из формулы моделей смешанных эффектов) - PullRequest
1 голос
/ 30 апреля 2019

Я хочу извлечь информацию из формул модели, особенно я хочу удалить случайные эффекты, чтобы просто получить «часть с фиксированными эффектами» из смешанных моделей (lme4-нотация).

Для этого я ищупоследний + в формуле перед парантезом ( найден.Все до + должно быть «фиксированной» частью формулы.Это прекрасно работает для моделей с предикторами / переменными с фиксированными эффектами.

Однако для моделей с нулевым значением (только для перехвата в фиксированных эффектах) может отсутствовать +, например, если формула имеет значение Reaction ~ (Days | Subject),В этом случае я проверяю, есть ли no + -sign.Но это не работает для моделей с несколькими случайными частями.В приведенных ниже примерах grepl() для f2 должен возвращать FALSE, но возвращает TRUE, потому что + находится для второго раскрывающего парантеза в случайных частях.

Мой вопрос: как я могу прекратить проверку на + после первого (, чтобы игнорировать возможный второй или третий термин случайного эффекта?Цель приведенного ниже примера состоит в том, чтобы grepl() -команды возвращали FALSE, FALSE, TRUE, TRUE.

f1 <- "Reaction ~ (1 + Days | Subject)"
f2 <- "Reaction ~ (1 | mygrp/mysubgrp) + (1 | Subject)"
f3 <- "Reaction ~ x1 + x2 + (1 + Days | Subject)"
f4 <- "Reaction ~ x1 + x2 + (1 | mygrp/mysubgrp) + (1 | Subject)"

# works!
grepl("\\+(\\s)*\\((.*)\\)", f1) # should return FALSE
#> [1] FALSE

# fails...
grepl("\\+(\\s)*\\((.*)\\)", f2) # should return FALSE
#> [1] TRUE

# works!
grepl("\\+(\\s)*\\((.*)\\)", f3) # should return TRUE
#> [1] TRUE

# works!
grepl("\\+(\\s)*\\((.*)\\)", f4) # should return TRUE
#> [1] TRUE

Ответы [ 2 ]

2 голосов
/ 30 апреля 2019

Это на самом деле не ответ на ваш вопрос с точки зрения RE (для которого, скорее всего, есть ответ), но если ваша цель состоит в том, чтобы извлечь случайные эффекты и / или формулы с фиксированными эффектами, вы можете получить больше от просмотра исходного кода. glFormula и lFormula образуют сам пакет lme4. Поскольку они создают матрицу проектирования X и Z для фиксированных и случайных эффектов соответственно, им придется извлекать отдельные части в некоторых точках.

Например, для извлечения фиксированных эффектов используются функции nobars и RHSForm:

library(lme4)
f1 <- Reaction ~ (1 + Days | Subject)
f2 <- Reaction ~ (1 | mygrp/mysubgrp) + (1 | Subject)
f3 <- Reaction ~ x1 + x2 + (1 + Days | Subject)
f4 <- Reaction ~ x1 + x2 + (1 | mygrp/mysubgrp) + (1 | Subject)
(f1FixedEffects <- nobars(lme4:::RHSForm(f1)) #note the triple 'lme4:::'. RHSForm is not exported to the public environment.
[1] 1
(f2FixedEffects <- nobars(lme4:::RHSForm(f2))
[1] 1
(f1FixedEffects <- nobars(lme4:::RHSForm(f3))
x1 + x2
(f1FixedEffects <- nobars(lme4:::RHSForm(f4))
x1 + x2

Если вы хотите извлечь всю формулу, вы можете использовать

lme4:::RHSForm(f1) <- nobars(lme4:::RHSForm(f1)
f1
Reaction ~ 1

или аналогичный (спасибо AkselA за его комментарий)

nobars(f1)
Reaction ~ 1

для фиксированных эффектов.

Обратите внимание, что я преобразовал ваши строковые формулы в формулы. Это также можно сделать с помощью функции as.formula ()

.
1 голос
/ 30 апреля 2019

Ответ Оливера верен, тем более что вы уже используете lme4, но есть также base каркас для изменения формул, который можно использовать.

# Is read as class formula
f4 <- Reaction ~ x1 + x2 + (1 | mygrp/mysubgrp) + (1 | Subject)

# Isolate the terms and find which contains a vertical bar
f4t <- terms(f4)
dr <- grep("|", labels(f4t), fixed=TRUE)

# Drop the term(s) containing a vertical bar
f4td <- drop.terms(f4t, dr)

# Update the old formula with the new set of terms
f4u <- update(f4, f4td)

# Voilà
f4u
# Reaction ~ x1 + x2

Как уже упоминалось в комментариях, это не удастся в двух частных случаях: все эффекты являются случайными, и никакие эффекты не являются случайными. Чтобы правильно обрабатывать эти исключения, я нашел, что лучше написать правильную функцию, пока я в ней.

drop_randfx <- function(form) {
    form.t <- terms(form)
    dr <- grepl("|", labels(form.t), fixed=TRUE)
    if (mean(dr) == 1) {
        form.u <- update(form, . ~ 1)
    } else {
        if (mean(dr) == 0) {
            form.u <- form
        } else {
            form.td <- drop.terms(form.t, which(dr))
            form.u <- update(form, form.td)
        }
    }
    form.u
}

Это проходит все тесты

f1 <- Reaction ~ (1 + Days | Subject)
f2 <- Reaction ~ (1 | mygrp/mysubgrp) + (1 | Subject)
f3 <- Reaction ~ x1 + x2 + (1 + Days | Subject)
f4 <- Reaction ~ x1 * x2 + (1 | mygrp/mysubgrp) + (1 | Subject)
f5 <- Reaction ~ x1 + x2

sapply(list(f1, f2, f3, f4, f5), drop_randfx)    # [[1]]

# [[1]]
# Reaction ~ 1
# 
# [[2]]
# Reaction ~ 1
# 
# [[3]]
# Reaction ~ x1 + x2
# 
# [[4]]
# Reaction ~ x1 + x2 + x1:x2
# 
# [[5]]
# Reaction ~ x1 + x2
...