¿Cómo puedo crear un conjunto de datos con dos columnas que tengan una correlación específica entre sí? Quiero poder definir la cantidad de valores que se crearán y especificar la correlación que debe tener la salida.

La pregunta es similar a esta: Generar números con correlación específica

Una de las respuestas fue usar:

out <- mvrnorm(10, mu = c(0,0), Sigma = matrix(c(1,0.56,0.56,1),, ncol = 2), 
                mpirical = TRUE)

Produciendo una salida como esta:

            [,1]         [,2]
 [1,] -0.4152618  0.033311146
 [2,]  0.7617759 -0.181852441
 [3,] -1.6393045 -1.054752469
 [4,] -1.7872420 -0.605214425
 [5,]  0.9581152  2.511000955
 [6,]  0.5048160 -0.278329145
 [7,]  0.8656220  0.483521747
 [8,] -0.1385699  0.017395548
 [9,]  0.3261103 -0.932889606
[10,]  0.5639388  0.007808691

Con la siguiente tabla de correlaciones cor (out):

     [,1] [,2]
[1,] 1.00 0.56
[2,] 0.56 1.00

Pero quiero que el conjunto de datos contenga números más altos, no negativos y más lejanos , por ejemplo:

       x   y
   1   5   5
   2  20  20
   3  30  30
   4 100 100

Teniendo una correlación de 1:

    x y
  x 1 1
  y 1 1

Con más lejos me refiero a "más" aleatorio y más grande en su valor como en mi muestra anterior.

¿Hay una forma (fácil) de archivar algo así?

2
Deset 9 feb. 2015 a las 21:38

2 respuestas

La mejor respuesta

La correlación no se ve afectada por la transformación lineal de las variables subyacentes. Entonces, la forma más directa de obtener lo que desea podría ser:

out <- as.data.frame(mvrnorm(10, mu = c(0,0), 
                     Sigma = matrix(c(1,0.56,0.56,1),, ncol = 2), 
                     empirical = TRUE))

out$V1.s <- (out$V1 - min(out$V1))*1000+10
out$V2.s <- (out$V2 - min(out$V2))*200+30

Ahora, el marco de datos out tiene columnas V1.s y V2.s "desplazadas" que no son negativas y son "grandes". Puede usar los números que desee en lugar de 1000, 10, 200 y 30 en mi código anterior. La respuesta de la correlación seguirá siendo 0,56.

> cor(out$V1.s, out$V2.s)
[1] 0.56
4
Curt F. 9 feb. 2015 a las 18:52

Gracias Curt F. Esto me ayudó a generar algunos conjuntos de datos de simulación. Agregué algunas opciones para especificar los aprox. media y rango deseados para X e Y. También proporciona salida para que pueda verificar la pendiente y la intersección, así como trazar los puntos y la línea de regresión.

library(MASS)
library(ggplot2)
# Desired correlation
d.cor <- 0.5
# Desired mean of X
d.mx <- 8
# Desired range of X
d.rangex <- 4
# Desired mean of Y
d.my <- 5
# Desired range of Y
d.rangey <- 2
# Calculations to create multipliation and addition factors for mean and range of X and Y
mx.factor <- d.rangex/6
addx.factor <- d.mx - (mx.factor*3)
my.factor <- d.rangey/6
addy.factor <- d.my - (my.factor*3)
# Generate data
out <- as.data.frame(mvrnorm(1000, mu = c(0,0), 
                             Sigma = matrix(c(1,d.cor,d.cor,1), ncol = 2), 
                             empirical = TRUE))
# Adjust so that values are positive and include factors to match desired means and ranges
out$V1.s <- (out$V1 - min(out$V1))*mx.factor + addx.factor
out$V2.s <- (out$V2 - min(out$V2))*my.factor + addy.factor
# Create liniear model to calculate intercept and slope
fit <- lm(out$V2.s ~ out$V1.s, data=out)
coef(fit)
# Plot scatterplot along with regression line
ggplot(out, aes(x=V1.s, y=V2.s)) + geom_point() + coord_fixed() + geom_smooth(method='lm')
# Produce summary table
summary(out)
2
mah271 11 jul. 2016 a las 17:59