Получить оценки модели с другого опорного уровня, не запуская новую модель?

#r #lme4 #coefficients #rstanarm #glmmtmb

#r #lme4 #коэффициенты #rstanarm #glmmtmb

Вопрос:

Мне интересно, есть ли простой способ изменить, какие значения находятся в перехвате, возможно, математически, без повторного запуска больших моделей. В качестве примера:

 mtcars$cyl<-as.factor(mtcars$cyl)

summary(
  lm(mpg~cyl hp,data=mtcars)
)
  

Вывод:

     Call:
lm(formula = mpg ~ cyl   hp, data = mtcars)

Residuals:
   Min     1Q Median     3Q    Max 
-4.818 -1.959  0.080  1.627  6.812 

Coefficients:
            Estimate Std. Error t value Pr(>|t|)    
(Intercept) 28.65012    1.58779  18.044  < 2e-16 ***
cyl6        -5.96766    1.63928  -3.640  0.00109 ** 
cyl8        -8.52085    2.32607  -3.663  0.00103 ** 
hp          -0.02404    0.01541  -1.560  0.12995    
---
Signif. codes:  0***0.001**0.01*0.05 ‘.’ 0.1 ‘ ’ 1

Residual standard error: 3.146 on 28 degrees of freedom
Multiple R-squared:  0.7539,    Adjusted R-squared:  0.7275 
F-statistic: 28.59 on 3 and 28 DF,  p-value: 1.14e-08
  

Теперь я могу изменить опорный уровень на 6 cyl и увидеть, как 8 cyl теперь сравнивается с 6 cyl, а не с 4 cyl:

 mtcars$cyl<-relevel(mtcars$cyl,"6")

summary(
  lm(mpg~cyl hp,data=mtcars)
)
  

Вывод:

 Call:
lm(formula = mpg ~ cyl   hp, data = mtcars)

Residuals:
   Min     1Q Median     3Q    Max 
-4.818 -1.959  0.080  1.627  6.812 

Coefficients:
            Estimate Std. Error t value Pr(>|t|)    
(Intercept) 22.68246    2.22805   10.18 6.48e-11 ***
cyl4         5.96766    1.63928    3.64  0.00109 ** 
cyl8        -2.55320    1.97867   -1.29  0.20748    
hp          -0.02404    0.01541   -1.56  0.12995    
---
Signif. codes:  0***0.001**0.01*0.05 ‘.’ 0.1 ‘ ’ 1

Residual standard error: 3.146 on 28 degrees of freedom
Multiple R-squared:  0.7539,    Adjusted R-squared:  0.7275 
F-statistic: 28.59 on 3 and 28 DF,  p-value: 1.14e-08
  

Что мне интересно, есть ли способ получить эти значения без повторного запуска модели? Вы можете видеть, что сравнение от 4 cyl до 6 cyl одинаково в каждой модели ( -5.96 и 5.96 ), но как мне получить оценку для «другого» коэффициента в любой модели (например -2.55 , из первой модели). Конечно, в этом случае для запуска другой модели требуется доля секунды. Но с очень большими моделями было бы удобно иметь возможность изменять опорный уровень без повторного запуска. Существуют ли относительно простые способы преобразовать все оценки и стандартные ошибки, основанные на другом опорном уровне, или это слишком сложно сделать?

Любые решения для lme4 , glmmTMB , или rstanarm моделей будут оценены.

Комментарии:

1. проверьте emmeans пакет.

2. Существует также multcomp::glht , который может позволить вам создавать запросы вручную.

3. потенциально полезно: stats.stackexchange.com/questions/168650 /…

Ответ №1:

Вот функция, которая выдаст вам коэффициенты для каждой перестановки заданной факторной переменной без необходимости повторного запуска модели или указания контрастов:

 rearrange_model_factors <- function(model, var)
{
  var   <- deparse(substitute(var))
  coefs <- coef(model)
  level_coefs <- grep(paste0("^", var), names(coefs))
  coefs[level_coefs] <- coefs[1]   coefs[level_coefs]
  used_levels <- gsub(var, "", names(coefs[level_coefs]))
  all_levels <- levels(model$model[[var]])
  names(coefs)[1] <- paste0(var, setdiff(all_levels, used_levels))
  level_coefs <- grep(paste0("^", var), names(coefs))
  levs <- coefs[level_coefs]
  perms <- gtools::permutations(length(levs), length(levs))
  perms <- lapply(seq(nrow(perms)), function(i) levs[perms[i,]])

  lapply(perms, function(x) { 
    x[-1] <- x[-1] - x[1]
    coefs[level_coefs] <- x
    names(coefs)[level_coefs] <- names(x)
    names(coefs)[1] <- "(Intercept)"
    coefs
    })
}
  

Предположим, у вас была такая модель:

 iris_mod <- lm(Sepal.Width ~ Species   Sepal.Length, data = iris)
  

Чтобы увидеть, как изменились бы ваши коэффициенты, если Species бы они были в другом порядке, вы бы просто сделали:

 rearrange_model_factors(iris_mod, Species)
#> [[1]]
#>       (Intercept) Speciesversicolor  Speciesvirginica      Sepal.Length 
#>         1.6765001        -0.9833885        -1.0075104         0.3498801 
#> 
#> [[2]]
#>       (Intercept)  Speciesvirginica Speciesversicolor      Sepal.Length 
#>         1.6765001        -1.0075104        -0.9833885         0.3498801 
#> 
#> [[3]]
#>      (Intercept)    Speciessetosa Speciesvirginica     Sepal.Length 
#>       0.69311160       0.98338851      -0.02412184       0.34988012 
#> 
#> [[4]]
#>      (Intercept) Speciesvirginica    Speciessetosa     Sepal.Length 
#>       0.69311160      -0.02412184       0.98338851       0.34988012 
#> 
#> [[5]]
#>       (Intercept)     Speciessetosa Speciesversicolor      Sepal.Length 
#>        0.66898976        1.00751035        0.02412184        0.34988012 
#> 
#> [[6]]
#>       (Intercept) Speciesversicolor     Speciessetosa      Sepal.Length 
#>        0.66898976        0.02412184        1.00751035        0.34988012 
  

Или на вашем собственном примере:

 mtcars$cyl <- as.factor(mtcars$cyl)

rearrange_model_factors(lm(mpg ~ cyl   hp, data = mtcars), cyl)
#> [[1]]
#> (Intercept)        cyl6        cyl8          hp 
#> 28.65011816 -5.96765508 -8.52085075 -0.02403883 
#> 
#> [[2]]
#> (Intercept)        cyl8        cyl6          hp 
#> 28.65011816 -8.52085075 -5.96765508 -0.02403883 
#> 
#> [[3]]
#> (Intercept)        cyl4        cyl8          hp 
#> 22.68246309  5.96765508 -2.55319567 -0.02403883 
#> 
#> [[4]]
#> (Intercept)        cyl8        cyl4          hp 
#> 22.68246309 -2.55319567  5.96765508 -0.02403883 
#> 
#> [[5]]
#> (Intercept)        cyl4        cyl6          hp 
#> 20.12926741  8.52085075  2.55319567 -0.02403883 
#> 
#> [[6]]
#> (Intercept)        cyl6        cyl4          hp 
#> 20.12926741  2.55319567  8.52085075 -0.02403883 
  

Нам нужно немного изложения, чтобы понять, почему это работает.

Хотя приведенная выше функция запускает модель только один раз, давайте начнем с создания списка, содержащего 3 версии mtcars , в которых уровни базовых коэффициентов cyl различны.

 df_list <- list(mtcars_4 = within(mtcars, cyl <- factor(cyl, c(4, 6, 8))),
                mtcars_6 = within(mtcars, cyl <- factor(cyl, c(6, 4, 8))),
                mtcars_8 = within(mtcars, cyl <- factor(cyl, c(8, 4, 6))))
  

Теперь мы можем извлечь коэффициенты вашей модели для всех трех версий сразу с помощью lapply . Для ясности мы удалим hp коэффициент, который все равно остается неизменным во всех трех версиях:

 coefs <- lapply(df_list, function(x) coef(lm(mpg ~ cyl   hp, data = x))[-4])

coefs
#> $mtcars_4
#> (Intercept)        cyl6        cyl8 
#>   28.650118   -5.967655   -8.520851 
#> 
#> $mtcars_6
#> (Intercept)        cyl4        cyl8 
#>   22.682463    5.967655   -2.553196 
#> 
#> $mtcars_8
#> (Intercept)        cyl4        cyl6 
#>   20.129267    8.520851    2.553196
  

Теперь мы напоминаем себе, что коэффициент для каждого уровня фактора задается относительно базового уровня. Это означает, что для коэффициентов без перехвата мы можем просто добавить значение перехвата к их коэффициентам, чтобы получить их абсолютное значение. Это означает, что эти числа представляют ожидаемое значение mpg , когда hp равно 0 для всех трех уровней cyl

 coefs <- lapply(coefs, function(x) c(x[1], x[-1]   x[1]))

coefs
#> $mtcars_4
#> (Intercept)        cyl6        cyl8 
#>    28.65012    22.68246    20.12927 
#> 
#> $mtcars_6
#> (Intercept)        cyl4        cyl8 
#>    22.68246    28.65012    20.12927 
#> 
#> $mtcars_8
#> (Intercept)        cyl4        cyl6 
#>    20.12927    28.65012    22.68246
  

Поскольку теперь у нас есть все три значения как абсолютные, давайте переименуем «Intercept» в соответствующий уровень фактора:

 coefs <- mapply(function(x, y) { names(x)[1] <- y; x}, 
                x = coefs, y = c("cyl4", "cyl6", "cyl8"), SIMPLIFY = FALSE)
coefs
#> $mtcars_4
#>     cyl4     cyl6     cyl8 
#> 28.65012 22.68246 20.12927 
#> 
#> $mtcars_6
#>     cyl6     cyl4     cyl8 
#> 22.68246 28.65012 20.12927 
#> 
#> $mtcars_8
#>     cyl8     cyl4     cyl6 
#> 20.12927 28.65012 22.68246
  

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

 coefs <- lapply(coefs, function(x) x[order(names(x))])

coefs
#> $mtcars_4
#>     cyl4     cyl6     cyl8 
#> 28.65012 22.68246 20.12927 
#> 
#> $mtcars_6
#>     cyl4     cyl6     cyl8 
#> 28.65012 22.68246 20.12927 
#> 
#> $mtcars_8
#>     cyl4     cyl6     cyl8 
#> 28.65012 22.68246 20.12927
  

Мы видим, что все они одинаковы. Вот почему порядок факторов является произвольным в lm : изменение порядка уровней факторов в конечном итоге дает те же числовые прогнозы, даже если сводка выглядит иначе.


TL; DR

Итак, ответ на ваш вопрос о том, где вы получаете -2.55, если у вас есть только первая модель, — это найти разницу между коэффициентами без перехвата. В этом случае

 (-8.520851) -(-5.967655) 
#> [1] -2.553196
  

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

Создано 2020-10-05 пакетом reprex (версия 0.3.0)

Комментарии:

1. Я не думаю, что это делает то, что хочет OP: они хотят иметь возможность извлекать коэффициенты / ошибки std и т.д. для модели с повторными параметрами без переоборудования модели . Я думаю, что предварительная установка всех возможных уровней не удовлетворяет этому запросу.

2. @BenBolker это не то, что я предлагаю. Я просто показываю эквивалентность различных упорядочений факторов. ОП спрашивает: » Но как мне получить оценку для «другого» коэффициента в любой модели (например, -2,55 из первой модели)». — и я показываю, как

3. @BenBolker я имею в виду, как получить коэффициенты по-другому упорядоченного фактора без повторного запуска модели. Извините, мое изложение не было более ясным.

4. вы показываете, как это сделать вручную. Я думаю, что OP ищет оборудование…

5. @Dylan_Gomes нет, SE и CI сложнее. Однако теперь вы знаете, что вам нужно только добавить перехват к коэффициентам фактора, чтобы получить абсолютные значения на каждом уровне, и SE останется прежним — вы можете рассчитать CI для каждого из них, используя этот факт.