Укажите корреляцию между различными перехватами с одинаковым уровнем в разных группах

Скажем, у меня есть две факторные переменные foo и bar, которые содержат одинаковые уровни "a", "b" и "c". Есть ли способ указать в lme4 (или любом другом пакете) модель со случайными перехватами для foo и bar с корреляцией между перехватами с одинаковым уровнем? Другими словами, я думаю, что эффект "a" в foo должен коррелировать с "a" в bar (аналогично для "b" и "c"). Формально это может выглядеть примерно так:

МВН

для каждого уровня k в ["a", "b", "c"].

Вот код, который оценивает sigma^2_foo и sigma^2_bar:

library(lme4)

levs <- c("a", "b", "c")
n <- 1000

df <- data.frame(y = rpois(n, 3.14),
                 foo = sample(levs, n, TRUE),
                 bar = sample(levs, n, TRUE))

mod <- glmer(y ~ (1 | foo) + (1 | bar), df, poisson)

> mod
Formula: y ~ (1 | foo) + (1 | bar)
Random effects:
 Groups Name        Std.Dev.
 foo    (Intercept) 0.009668
 bar    (Intercept) 0.006739

но, конечно, пропускает член корреляции rho. Можно ли добавить эту корреляционную структуру в эту модель?

ОБНОВЛЕНИЕ

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

data {
    int<lower = 1> num_data;
    int<lower = 1> num_levels;

    int<lower = 0> y[num_data];

    int<lower = 1, upper = num_levels> foo_ix[num_data];
    int<lower = 1, upper = num_levels> bar_ix[num_data];
}

parameters {
    real alpha;

    vector[num_levels] alpha_foo;
    vector[num_levels] alpha_bar;

    real<lower = 0.0> sigma_foo;
    real<lower = 0.0> sigma_bar;

    real<lower = -1.0, upper = 1.0> rho;
}

transformed parameters {
    matrix[2, 2] Sigma;
    Sigma[1, 1] = square(sigma_foo);
    Sigma[2, 1] = rho * sigma_foo * sigma_bar;
    Sigma[1, 2] = rho * sigma_foo * sigma_bar;
    Sigma[2, 2] = square(sigma_bar);
}

model {
    for (i in 1:num_levels) {
        [alpha_foo[i], alpha_bar[i]] ~ multi_normal([0.0, 0.0], Sigma);
    }

    y ~ poisson_log(alpha + alpha_foo[foo_ix] + alpha_bar[bar_ix]);
}

person Jeff    schedule 24.04.2019    source источник
comment
Вы много смотрели на nlme? Насколько я понимаю, вы можете закодировать свои собственные структуры ковариации, по крайней мере, для моделей с линейными случайными эффектами. Вы можете быть ограничены в том, какие оптимизаторы вы можете использовать, а также не можете делать такие вещи, как биномиальный glmm с nlme, но это может работать для ваших целей? например stackoverflow.com/q/39291148/8400969   -  person Michael    schedule 04.05.2019
comment
С nlme не очень знаком - посмотрю, спасибо!   -  person Jeff    schedule 06.05.2019


Ответы (1)


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

mod <- glmer(y ~ (1 | foo) + (1 | bar) + foo:bar, df, poisson)
summary(mod)

Это даст следующий результат:

Generalized linear mixed model fit by maximum likelihood (Laplace Approximation) [glmerMod]
 Family: poisson  ( log )
Formula: y ~ (1 | foo) + (1 | bar) + foo:bar
   Data: df

     AIC      BIC   logLik deviance df.resid 
  3962.1   4016.1  -1970.1   3940.1      989 

Scaled residuals: 
    Min      1Q  Median      3Q     Max 
-1.8572 -0.6665 -0.0947  0.5406  3.8695 

Random effects:
 Groups Name        Variance Std.Dev.
 foo    (Intercept) 0        0       
 bar    (Intercept) 0        0       
Number of obs: 1000, groups:  foo, 3; bar, 3

Fixed effects:
            Estimate Std. Error z value Pr(>|z|)    
(Intercept)  1.07131    0.05882  18.212   <2e-16 ***
fooa:bara    0.16682    0.07692   2.169   0.0301 *  
foob:bara    0.04549    0.08039   0.566   0.5715    
fooc:bara   -0.08801    0.08464  -1.040   0.2984    
fooa:barb    0.08196    0.08370   0.979   0.3275    
foob:barb    0.05421    0.08006   0.677   0.4983    
fooc:barb    0.08886    0.07712   1.152   0.2492    
fooa:barc   -0.02109    0.07884  -0.268   0.7891    
foob:barc    0.12437    0.07720   1.611   0.1072    
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

Correlation of Fixed Effects:
          (Intr) foo:br fob:br foc:br fo:brb fb:brb fc:brb fo:brc
fooa:bara -0.765                                                 
foob:bara -0.732  0.560                                          
fooc:bara -0.695  0.531  0.509                                   
fooa:barb -0.703  0.537  0.514  0.488                            
foob:barb -0.735  0.562  0.538  0.511  0.516                     
fooc:barb -0.763  0.583  0.558  0.530  0.536  0.560              
fooa:barc -0.746  0.571  0.546  0.519  0.524  0.548  0.569       
foob:barc -0.762  0.583  0.558  0.530  0.535  0.560  0.581  0.569

Конечно, как вы могли видеть, взаимодействие здесь происходит между всеми уровнями вместе (не обусловленными, как вы хотите). Надеюсь, вы сможете получить мой ответ в качестве первого шага к получению желаемого решения. Я также постараюсь понять это для вас и обновлю свой ответ, как только найду что-то полезное. Мое первое впечатление заключается в том, что вам нужно изменить свой фрейм данных таким образом, чтобы вы могли контролировать взаимодействие между перехватами одного уровня.


[ОБНОВЛЕНИЕ]

Вы можете добавить переменную взаимодействия вручную, примерно так:

df <- transform(df,foo_bar.inter=interaction(foo,bar, sep = ":"))

а затем вы можете оставить только a с a, b с b и c с c следующим образом:

df$foo_bar.inter[df$foo != df$bar] <- NA

Вы можете попробовать и дайте мне знать, если вам нужна дополнительная помощь.

Удачи.

person Taher Ahmed Ghaleb    schedule 01.05.2019
comment
Большое спасибо за ответ @TeeKea (+1), но я не думаю, что это совсем то, что я ищу. Я не хочу добавлять никаких фиксированных эффектов — только один гиперпараметр для корреляции случайных перехватов с соответствующими уровнями. Не уверен, что это будет полезно, но я добавил немного кода Стэна, чтобы показать, как его можно закодировать в Стэне. - person Jeff; 02.05.2019