Générez deux échantillons de données corrélées à partir d'une distribution aléatoire normale standard suite à une corrélation prédéterminée .
Par exemple, prenons une corrélation r = 0,7 et codons une matrice de corrélation telle que:
(C <- matrix(c(1,0.7,0.7,1), nrow = 2))
[,1] [,2]
[1,] 1.0 0.7
[2,] 0.7 1.0
Nous pouvons utiliser mvtnorm
pour générer maintenant ces deux échantillons comme un vecteur aléatoire bivarié:
set.seed(0)
SN <- rmvnorm(mean = c(0,0), sig = C, n = 1e5)
résultant en deux composantes vectorielles distribuées comme ~ et avec a . Les deux composants peuvent être extraits comme suit:N(0,1)cor(SN[,1],SN[,2])= 0.6996197 ~ 0.7
X1 <- SN[,1]; X2 <- SN[,2]
Voici l'intrigue avec la ligne de régression qui se chevauche:
Utilisez la transformation intégrale de probabilité ici pour obtenir un vecteur aléatoire bivarié avec des distributions marginales ~ et la même corrélation :U(0,1)
U <- pnorm(SN)
- donc nous alimentons pnorm
le SN
vecteur pour trouver (ou ). Ce faisant, nous préservons le .erf(SN)Φ(SN)cor(U[,1], U[,2]) = 0.6816123 ~ 0.7
Encore une fois, nous pouvons décomposer le vecteur U1 <- U[,1]; U2 <- U[,2]
et produire un diagramme de dispersion avec des distributions marginales sur les bords, montrant clairement leur nature uniforme:
Appliquez ici la méthode d'échantillonnage par transformée inverse pour finalement obtenir le bivecteur de points également corrélés appartenant à la famille de distribution que nous nous proposons de reproduire.
De là, nous pouvons simplement générer deux vecteurs distribués normalement et avec des variances égales ou différentes . Par exemple: Y1 <- qnorm(U1, mean = 8,sd = 10)
et Y2 <- qnorm(U2, mean = -5, sd = 4)
qui maintiendra la corrélation désirée, cor(Y1,Y2) = 0.6996197 ~ 0.7
.
Ou optez pour différentes distributions. Si les distributions choisies sont très différentes, la corrélation peut ne pas être aussi précise. Par exemple, U1
suivons une distribution avec 3 df, et une exponentielle avec a = 1: et The . Voici les histogrammes respectifs:tU2
λZ1 <- qt(U1, df = 3)
Z2 <- qexp(U2, rate = 1)
cor(Z1,Z2) [1] 0.5941299 < 0.7
Voici un exemple de code pour tout le processus et les marginaux normaux:
Cor_samples <- function(r, n, mean1, mean2, sd1, sd2){
C <- matrix(c(1,r,r,1), nrow = 2)
require(mvtnorm)
SN <- rmvnorm(mean = c(0,0), sig = C, n = n)
U <- pnorm(SN)
U1 <- U[,1]
U2 <- U[,2]
Y1 <<- qnorm(U1, mean = mean1,sd = sd1)
Y2 <<- qnorm(U2, mean = mean2,sd = sd2)
sample_measures <<- as.data.frame(c(mean(Y1), mean(Y2), sd(Y1), sd(Y2), cor(Y1,Y2)), names<-c("mean Y1", "mean Y2", "SD Y1", "SD Y2", "Cor(Y1,Y2)"))
sample_measures
}
À titre de comparaison, j'ai mis en place une fonction basée sur la décomposition de Cholesky:
Cholesky_samples <- function(r, n, mean1, mean2, sd1, sd2){
C <- matrix(c(1,r,r,1), nrow = 2)
L <- chol(C)
X1 <- rnorm(n)
X2 <- rnorm(n)
X <- rbind(X1,X2)
Y <- t(L)%*%X
Y1 <- Y[1,]
Y2 <- Y[2,]
N_1 <<- Y[1,] * sd1 + mean1
N_2 <<- Y[2,] * sd2 + mean2
sample_measures <<- as.data.frame(c(mean(N_1), mean(N_2), sd(N_1), sd(N_2), cor(N_1, N_2)),
names<-c("mean N_1", "mean N_2", "SD N_1", "SD N_2","cor(N_1,N_2)"))
sample_measures
}
En essayant les deux méthodes pour générer des échantillons corrélés (disons ) distribués ~ et nous obtenons, en définissant :r=0.7N(97,23)N(32,8)set.seed(99)
Utilisation de l'uniforme:
cor_samples(0.7, 1000, 97, 32, 23, 8)
c(mean(Y1), mean(Y2), sd(Y1), sd(Y2), cor(Y1, Y2))
mean Y1 96.5298821
mean Y2 32.1548306
SD Y1 22.8669448
SD Y2 8.1150780
cor(Y1,Y2) 0.7061308
et utilisation du Cholesky:
Cholesky_samples(0.7, 1000, 97, 32, 23, 8)
c(mean(N_1), mean(N_2), sd(N_1), sd(N_2), cor(N_1, N_2))
mean N_1 96.4457504
mean N_2 31.9979675
SD N_1 23.5255419
SD N_2 8.1459100
cor(N_1,N_2) 0.7282176