【问题标题】:Generate random values in R with a defined correlation in a defined range在 R 中生成具有定义范围内定义相关性的随机值
【发布时间】:2017-07-03 14:14:29
【问题描述】:

对于一个科学项目,我正在寻找一种方法来生成一定范围内的随机数据(例如 min=0,max=100000),并与另一个在 R 中已经存在的变量具有一定的相关性>。目标是稍微丰富数据集,这样我就可以生成一些更有意义的图表(不用担心,我正在处理虚构数据)。

例如,我想使用以下数据生成与 r=-.78 相关的随机值:

var1 <- rnorm(100, 50, 10)

我已经遇到了一些非常好的解决方案(即https://stats.stackexchange.com/questions/15011/generate-a-random-variable-with-a-defined-correlation-to-an-existing-variable),但只能得到非常小的值,我无法对其进行转换,因此在其他原始值的上下文中是有意义的。

如下示例:

var1 <- rnorm(100, 50, 10)
n     <- length(var1)                   
rho   <- -0.78                   
theta <- acos(rho)             
x1    <- var1      
x2    <- rnorm(n, 50, 50)      
X     <- cbind(x1, x2)         
Xctr  <- scale(X, center=TRUE, scale=FALSE)   

Id   <- diag(n)                               
Q    <- qr.Q(qr(Xctr[ , 1, drop=FALSE]))       
P    <- tcrossprod(Q)          # = Q Q'       
x2o  <- (Id-P) %*% Xctr[ , 2]                 
Xc2  <- cbind(Xctr[ , 1], x2o)                
Y    <- Xc2 %*% diag(1/sqrt(colSums(Xc2^2)))  
var2 <- Y[ , 2] + (1 / tan(theta)) * Y[ , 1]    
cor(var1, var2)  

我得到的 var2 值介于 -0.5 和 0.5 之间。平均值为 0。我想要更多的分布式数据,所以我可以简单地通过添加 50 来转换它,并且与我的第一个变量相比具有非常相似的范围。

你们中有人知道生成这种或多或少有意义的数据的方法吗?

提前非常感谢!

【问题讨论】:

  • 你可以只使用线性变换。 r-value 将保持不变
  • 您所做的似乎是生成完全随机的数据,并对其进行调整以使相关性正确。您也可以做相反的事情并在源数据上产生噪声,然后将其放大以获得所需的相关性,也许您会更接近原始形状。

标签: r random correlation generated


【解决方案1】:

var1开头,重命名为A,使用10000分:

set.seed(1)
A <- rnorm(10000,50,10)  # Mean of 50

首先将A 中的值转换为具有新的所需平均值50,000 并具有反比关系(即减法):

B <- 1e5 - (A*1e3) # Note that { mean(A) * 1000 = 50,000 }

这只会产生r = -1。添加一些噪音以达到所需的r

B <- B + rnorm(10000,0,8.15e3) # Note this noise has mean = 0
                               # the amount of noise, 8.15e3, was found through parameter-search

这有你想要的相关性:

cor(A,B)
[1] -0.7805972

查看方式:

plot(A,B)

注意
您的 B 值可能超出您的范围 0 100,000。如果您使用不同的种子或生成更多数字,您可能需要过滤超出范围的值。

也就是说,目前的范围很好:

range(B)
[1]  1668.733 95604.457

【讨论】:

  • 非常感谢!我真的很喜欢你的解决方案,我唯一不明白的是,你是如何发现噪音的。你评论了参数搜索,你能给我解释一下吗?
  • 我只是尝试了 sd 的不同值,直到达到您想要的 r 值。您可以通过迭代一系列值或类似梯度搜索的方法来编写参数搜索操作,但您可能想先尝试自己编写代码,如果遇到困难,将其作为单独的问题发布。
  • 这正是我需要的提示。非常感谢您的帮助!
【解决方案2】:

如果您对生成值的相关性和边际分布(即形状)感到满意,请将值(介于 (-.5, +.5) 之间)乘以 100,000 并加上 50,000。

> c(-0.5, 0.5) * 100000 + 50000
[1] 0e+00 1e+05

edit:这种方法,或任何其他将 100,000 和 50,000 交换为不同数字的方法,将是 @gregor-de-cillia 推荐的“线性变换”示例。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2016-10-20
    • 1970-01-01
    • 2014-07-13
    • 2016-05-04
    • 1970-01-01
    相关资源
    最近更新 更多