Genere dos muestras de datos correlacionados a partir de una distribución aleatoria normal estándar siguiendo una correlación predeterminada .
Como ejemplo, escojamos una correlación r = 0.7 y codifiquemos una matriz de correlación como:
(C <- matrix(c(1,0.7,0.7,1), nrow = 2))
[,1] [,2]
[1,] 1.0 0.7
[2,] 0.7 1.0
Podemos usar mvtnorm
para generar ahora estas dos muestras como un vector aleatorio bivariado:
set.seed(0)
SN <- rmvnorm(mean = c(0,0), sig = C, n = 1e5)
resultando en dos componentes vectoriales distribuidos como ~ y con a . Ambos componentes se pueden extraer de la siguiente manera:N(0,1)cor(SN[,1],SN[,2])= 0.6996197 ~ 0.7
X1 <- SN[,1]; X2 <- SN[,2]
Aquí está la trama con la línea de regresión superpuesta:
Use la Transformación integral de probabilidad aquí para obtener un vector aleatorio bivariado con distribuciones marginales ~U(0,1) y la misma correlación :
U <- pnorm(SN)
- entonces estamos alimentando pnorm
el SN
vector para encontrarerf(SN) (o Φ(SN)) En el proceso, preservamos el cor(U[,1], U[,2]) = 0.6816123 ~ 0.7
.
Nuevamente podemos descomponer el vector U1 <- U[,1]; U2 <- U[,2]
y producir un diagrama de dispersión con distribuciones marginales en los bordes, mostrando claramente su naturaleza uniforme:
Aplique el método de muestreo de transformación inversa aquí para obtener finalmente el bivector de puntos igualmente correlacionados que pertenezcan a cualquier familia de distribución que nos propongamos reproducir.
A partir de aquí, podemos generar dos vectores distribuidos normalmente y con variaciones iguales o diferentes . Por ejemplo: Y1 <- qnorm(U1, mean = 8,sd = 10)
y Y2 <- qnorm(U2, mean = -5, sd = 4)
, que mantendrá la correlación deseada, cor(Y1,Y2) = 0.6996197 ~ 0.7
.
O optar por diferentes distribuciones. Si las distribuciones elegidas son muy diferentes, la correlación puede no ser tan precisa. Por ejemplo, sigamos U1
atdistribución con 3 df, y U2
una exponencial con unλ= 1: Z1 <- qt(U1, df = 3)
y Z2 <- qexp(U2, rate = 1)
el cor(Z1,Z2) [1] 0.5941299 < 0.7
. Aquí están los histogramas respectivos:
Aquí hay un ejemplo de código para todo el proceso y los márgenes normales:
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
}
A modo de comparación, he reunido una función basada en la descomposición 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
}
Probar ambos métodos para generar correlacionados (por ejemplo, r=0.7) muestras distribuidas ~ N(97,23) y N(32,8)obtenemos, configurando set.seed(99)
:
Usando el 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
y usando el 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