@Wolfgang a déjà donné une excellente réponse. Je veux développer un peu pour montrer que vous pouvez également arriver à l'ICC estimé de 0,75 dans son exemple de jeu de données en implémentant littéralement l'algorithme intuitif de sélection aléatoire de nombreuses paires de valeurs - où les membres de chaque paire proviennent de la même groupe - puis simplement calculer leur corrélation. Et puis cette même procédure peut facilement être appliquée à des ensembles de données avec des groupes de n'importe quelle taille, comme je le montrerai également.y
Nous chargeons d'abord le jeu de données de @ Wolfgang (non illustré ici). Définissons maintenant une fonction R simple qui prend un data.frame et renvoie une seule paire d'observations sélectionnées au hasard dans le même groupe:
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"])
}
Voici un exemple de ce que nous obtenons si nous appelons cette fonction 10 fois sur le jeu de données de @ 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
Maintenant, pour estimer l'ICC, nous appelons simplement cette fonction un grand nombre de fois, puis calculons la corrélation entre les deux colonnes.
random_pairs <- replicate(100000, get_random_pair(dat))
cor(t(random_pairs))
# [,1] [,2]
# [1,] 1.0000000 0.7493072
# [2,] 0.7493072 1.0000000
Cette même procédure peut être appliquée, sans aucune modification, aux ensembles de données avec des groupes de n'importe quelle taille. Par exemple, créons un ensemble de données composé de 100 groupes de 100 observations chacun, avec le vrai ICC réglé à 0,75 comme dans l'exemple de @ 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")
En estimant l'ICC sur la base des composantes de la variance à partir d'un modèle mixte, nous obtenons:
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
Et si nous appliquons la procédure d'appariement aléatoire, nous obtenons
random_pairs <- replicate(100000, get_random_pair(dat))
cor(t(random_pairs))
# [,1] [,2]
# [1,] 1.0000000 0.7503004
# [2,] 0.7503004 1.0000000
qui concorde étroitement avec l’estimation de la composante de variance.
Notez que bien que la procédure d'appariement aléatoire soit plutôt intuitive et didactiquement utile, la méthode illustrée par @Wolfgang est en réalité beaucoup plus intelligente. Pour un ensemble de données comme celui-ci de taille 100 * 100, le nombre d'appariements intra-groupe uniques (hors auto-appariements) est de 505 000 - un grand nombre mais pas astronomique - il nous est donc tout à fait possible de calculer la corrélation de l'ensemble complètement épuisé de tous les appariements possibles, plutôt que de devoir échantillonner au hasard à partir de l'ensemble de données. Voici une fonction pour récupérer tous les appariements possibles pour le cas général avec des groupes de toute taille:
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"])
}))
}
Maintenant, si nous appliquons cette fonction à l'ensemble de données 100 * 100 et calculons la corrélation, nous obtenons:
cor(get_all_pairs(dat))
# [,1] [,2]
# [1,] 1.0000000 0.7504817
# [2,] 0.7504817 1.0000000
Ce qui est bien en accord avec les deux autres estimations, et par rapport à la procédure d'appariement aléatoire, est beaucoup plus rapide à calculer et devrait également être une estimation plus efficace dans le sens d'avoir moins de variance.