¿Cómo reorganizar los datos 2D para obtener la correlación dada?

9

Tengo el siguiente conjunto de datos simple con dos variables continuas; es decir:

d = data.frame(x=runif(100,0,100),y = runif(100,0,100))
plot(d$x,d$y)
abline(lm(y~x,d), col="red")
cor(d$x,d$y) # = 0.2135273

Distribución base

Necesito reorganizar los datos para que la correlación entre las variables sea ~ 0.6. Necesito mantener constantes las medias y otras estadísticas descriptivas (sd, min, max, etc.) de ambas variables.

Sé que es posible hacer casi cualquier correlación con los datos dados, es decir:

d2 = with(d,data.frame(x=sort(x),y=sort(y)))
plot(d2$x,d2$y)
abline(lm(y~x,d2), col="red")
cor(d2$x,d2$y) # i.e. 0.9965585

ingrese la descripción de la imagen aquí

Si trato de usar la samplefunción para esta tarea:

cor.results = c()
for(i in 1:1000){
    set.seed(i)
    d3 = with(d,data.frame(x=sample(x),y=sample(y)))
    cor.results =  c(cor.results,cor(d3$x,d3$y))
}

Obtengo una amplia gama de correlaciones:

> summary(cor.results)
     Min.   1st Qu.    Median      Mean   3rd Qu.      Max. 
-0.281600 -0.038330 -0.002498 -0.001506  0.034380  0.288800

pero este rango depende del número de filas en el marco de datos y disminuye con el aumento de tamaño.

> d = data.frame(x=runif(1000,0,100),y = runif(1000,0,100))
> cor.results = c()
> for(i in 1:1000){
+ set.seed(i)
+ d3 = with(d,data.frame(x=sample(x),y=sample(y)))
+ cor.results =  c(cor.results,cor(d3$x,d3$y))
+ }
> summary(cor.results)
      Min.    1st Qu.     Median       Mean    3rd Qu.       Max. 
-0.1030000 -0.0231300 -0.0005248 -0.0005547  0.0207000  0.1095000

Mi pregunta es:

¿Cómo reorganizar dicho conjunto de datos para obtener una correlación dada (es decir, 0.7)? (También será bueno si el método eliminará la dependencia del tamaño del conjunto de datos)

Yuriy Petrovskiy
fuente

Respuestas:

6

Aquí hay una forma de reorganizar los datos que se basan en generar números aleatorios adicionales.

Dibujamos muestras de una distribución normal bivariada con correlación especificada. A continuación, calculamos los rangos de los valores e que obtenemos. Estos rangos se utilizan para ordenar los valores originales. Para este enfoque, tenemos una clasificación superior de los valores originales e .y x yxyxy

Primero, creamos el conjunto de datos real (como en su ejemplo).

set.seed(1)
d <- data.frame(x = runif(100, 0, 100), y = runif(100, 0, 100))

cor(d$x, d$y)
# [1] 0.01703215

Ahora, especificamos una matriz de correlación.

corr <- 0.7  # target correlation
corr_mat <- matrix(corr, ncol = 2, nrow = 2)
diag(corr_mat) <- 1
corr_mat
#      [,1] [,2]
# [1,]  1.0  0.7
# [2,]  0.7  1.0

Generamos datos aleatorios siguiendo una distribución normal bivariada con , (para ambas variables) y la correlación especificada. En R, esto se puede hacer con la función del paquete. Usamos para indicar que la correlación es la correlación empírica (no la correlación de la población).σ = 1μ=0σ=1mvrnormMASSempirical = TRUE

library(MASS)
mvdat <- mvrnorm(n = nrow(d), mu = c(0, 0), Sigma = corr_mat, empirical = TRUE)

cor(mvdat)
#      [,1] [,2]
# [1,]  1.0  0.7
# [2,]  0.7  1.0

Los datos aleatorios coinciden perfectamente con la correlación especificada.

A continuación, calculamos los rangos de los datos aleatorios.

rx <- rank(mvdat[ , 1], ties.method = "first")
ry <- rank(mvdat[ , 2], ties.method = "first")

Para usar los rangos de los datos originales d, tenemos que ordenar los datos originales.

dx_sorted <- sort(d$x)
dy_sorted <- sort(d$y)

Ahora, podemos usar los rangos para especificar el orden de los datos ordenados.

cor(dx_sorted[rx], dy_sorted[ry])
# [1] 0.6868986

La correlación obtenida no coincide perfectamente con la especificada, pero la diferencia es relativamente pequeña.

Aquí, dx_sorted[rx]y dy_sorted[ry]son versiones remuestreadas de los datos originales en d.

Sven Hohenstein
fuente
2
+1 Eso es bastante genial. Los pasos son 1) generar datos normales con la correlación correcta de Pearson, 2) hacer que los datos originales y los datos generados coincidan exactamente con las correlaciones de rango, 3) los datos originales tienen aproximadamente la misma correlación de Pearson ahora. ¿Por qué funciona esto? ¿Hay un resultado analítico que indique que sí? ¿Desigualdades limitantes que mantienen las diversas medidas de correlación cercanas entre sí para distribuciones con buen comportamiento o algo así?
Bill
1
@Bill No puedo explicar el enfoque analíticamente. Es solo una idea que me vino a la mente. Sin embargo, resumió los pasos de una manera agradable. Gracias.
Sven Hohenstein
2

Para generar dos distribuciones uniformes con una correlación especificada, funcionará el algoritmo de Ruscio y Kaczetow (2008). Proporcionan código R . Luego puede transformar con una función lineal simple para obtener su objetivo min, max, mean y SD.

Algoritmo de Ruscio y Kaczetow

Resumiré el caso bivariado, pero también puede funcionar con problemas multivariados. No correlacionadas y se generan con cualquier forma (por ejemplo, uniforme). Luego, e se generan como normales bivariadas con una correlación intermedia. e se reemplazan por e de una manera que preserva el rango. Ajuste la correlación intermedia para que sea mayor o menor dependiendo de si r ( ) es demasiado baja o demasiado alta. e se generan como normales bivariadas con la nueva correlación intermedia. Repetir.XoYoX1Y1X1Y1X0Y0X1,Y1X2Y2

Tenga en cuenta que esto es muy similar a la solución de @Sven Hohenstein, excepto que es iterativa, por lo que la correlación intermedia se acercará cada vez más a la correlación objetivo hasta que sean indistinguibles. Además, tenga en cuenta que este algoritmo se puede usar para generar una gran población (p. Ej., N = 1 millón) de la cual extraer muestras más pequeñas, lo cual es útil si necesita tener un error de muestreo.

Para una publicación relacionada: Correlación y distribuciones no normales

Preservar estadísticas descriptivas

No hay garantía de que el algoritmo produzca exactamente los mismos descriptivos. Sin embargo, debido a que la media y la DE de una distribución uniforme están determinadas por su mínimo y máximo, simplemente puede ajustar el mínimo y el máximo para arreglar todo.

Deje que e sean sus variables generadas a partir de la última iteración del algoritmo de Ruscio & Kaczetow, e sean sus variables finales que espera tener (con descriptivos de destino), y e serán sus variables originales en su conjunto de datos. XgYgXfYfXY

Calcular Xf=(Xgmin(X))(max(X)min(x))/(max(Xg)min(Xg))

Haga lo mismo paraYf

Referencia:

Ruscio, J. y Kaczetow, W. (2008). Simulación de datos no normales multivariados utilizando un algoritmo iterativo. Investigación conductual multivariante, 43, 355-381. doi: 10.1080 / 00273170802285693

Antonio
fuente
1

Supongo que cuando dices "remuestreo" te refieres a "simular", que es más general. La siguiente es la forma más concisa que sé para simular datos bivariados normales con una correlación específica. Sustituya sus propios valores deseados para r y n.

r = .6
n = 1000
x = rnorm(n) 
z = rnorm(n) 
y = (r/(1-r^2)^.5)*x + z

cor(x,y)
plot(x,y)
abline(lm(y~x), col="red")
rolando2
fuente
3
No, realmente quiero decir "remuestreo". Necesito mantener constantes las medias y otras estadísticas descriptivas (sd, min, max) de ambas variables. Se actualizó la pregunta.
Yuriy Petrovskiy