@ Wolfgang ha già dato un'ottima risposta. Voglio espanderlo un po 'per mostrare che puoi anche arrivare all'ICC stimato di 0,75 nel suo set di dati di esempio implementando letteralmente l'algoritmo intuitivo di selezione casuale di molte coppie di valori - dove i membri di ciascuna coppia provengono dal stesso gruppo - e quindi semplicemente calcolando la loro correlazione. E quindi questa stessa procedura può essere facilmente applicata a set di dati con gruppi di qualsiasi dimensione, come mostrerò anche.y
Per prima cosa cariciamo il set di dati di @ Wolfgang (non mostrato qui). Ora definiamo una semplice funzione R che accetta un data.frame e restituisce una singola coppia di osservazioni selezionate casualmente dallo stesso gruppo:
get_random_pair <- function(df){
# select a random row
i <- sample(nrow(df), 1)
# select a random other row from the same group
# (the call to rep() here is admittedly odd, but it's to avoid unwanted
# behavior when the first argument to sample() has length 1)
j <- sample(rep(setdiff(which(dat$group==dat[i,"group"]), i), 2), 1)
# return the pair of y-values
c(df[i,"y"], df[j,"y"])
}
Ecco un esempio di ciò che otteniamo se chiamiamo questa funzione 10 volte nel set di dati di @ Wolfgang:
test <- replicate(10, get_random_pair(dat))
t(test)
# [,1] [,2]
# [1,] 9 6
# [2,] 2 2
# [3,] 2 4
# [4,] 3 5
# [5,] 3 2
# [6,] 2 4
# [7,] 7 9
# [8,] 5 3
# [9,] 5 3
# [10,] 3 2
Ora per stimare l'ICC, chiamiamo questa funzione un gran numero di volte e quindi calcoliamo la correlazione tra le due colonne.
random_pairs <- replicate(100000, get_random_pair(dat))
cor(t(random_pairs))
# [,1] [,2]
# [1,] 1.0000000 0.7493072
# [2,] 0.7493072 1.0000000
Questa stessa procedura può essere applicata, senza alcuna modifica, a set di dati con gruppi di qualsiasi dimensione. Ad esempio, creiamo un set di dati composto da 100 gruppi di 100 osservazioni ciascuno, con il vero ICC impostato su 0,75 come nell'esempio di @ Wolfgang.
set.seed(12345)
group_effects <- scale(rnorm(100))*sqrt(4.5)
errors <- scale(rnorm(100*100))*sqrt(1.5)
dat <- data.frame(group = rep(1:100, each=100),
person = rep(1:100, times=100),
y = rep(group_effects, each=100) + errors)
stripchart(y ~ group, data=dat, pch=20, col=rgb(0,0,0,.1), ylab="group")
Stimando l'ICC in base ai componenti di varianza di un modello misto, otteniamo:
library("lme4")
mod <- lmer(y ~ 1 + (1|group), data=dat, REML=FALSE)
summary(mod)
# Random effects:
# Groups Name Variance Std.Dev.
# group (Intercept) 4.502 2.122
# Residual 1.497 1.223
# Number of obs: 10000, groups: group, 100
4.502/(4.502 + 1.497)
# 0.7504584
E se applichiamo la procedura di accoppiamento casuale, otteniamo
random_pairs <- replicate(100000, get_random_pair(dat))
cor(t(random_pairs))
# [,1] [,2]
# [1,] 1.0000000 0.7503004
# [2,] 0.7503004 1.0000000
che concorda strettamente con la stima della componente di varianza.
Si noti che mentre la procedura di accoppiamento casuale è piuttosto intuitiva e didatticamente utile, il metodo illustrato da @Wolfgang è in realtà molto più intelligente. Per un set di dati come questo di dimensioni 100 * 100, il numero di accoppiamenti univoci all'interno del gruppo (esclusi gli auto-accoppiamenti) è 505.000 - un numero grande ma non astronomico - quindi è totalmente possibile per noi calcolare la correlazione dell'insieme completamente esaurito di tutti i possibili accoppiamenti, piuttosto che dover campionare casualmente dal set di dati. Ecco una funzione per recuperare tutti gli accoppiamenti possibili per il caso generale con gruppi di qualsiasi dimensione:
get_all_pairs <- function(df){
# do this for every group and combine the results into a matrix
do.call(rbind, by(df, df$group, function(group_df){
# get all possible pairs of indices
i <- expand.grid(seq(nrow(group_df)), seq(nrow(group_df)))
# remove self-pairings
i <- i[i[,1] != i[,2],]
# return a 2-column matrix of the corresponding y-values
cbind(group_df[i[,1], "y"], group_df[i[,2], "y"])
}))
}
Ora se applichiamo questa funzione al set di dati 100 * 100 e calcoliamo la correlazione, otteniamo:
cor(get_all_pairs(dat))
# [,1] [,2]
# [1,] 1.0000000 0.7504817
# [2,] 0.7504817 1.0000000
Che concorda bene con le altre due stime, e rispetto alla procedura di accoppiamento casuale, è molto più veloce da calcolare e dovrebbe anche essere una stima più efficiente nel senso di avere una minore varianza.