如何重新排列二维数据以获得给定的相关性?

机器算法验证 r 相关性
2022-03-08 14:11:36

我有以下带有两个连续变量的简单数据集;IE:

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

基地分布

我需要重新排列数据以使变量之间的相关性达到~0.6。我需要保持两个变量的均值和其他描述性统计数据(sd、min、max 等)不变。

我知道几乎可以与给定数据建立任何关联,即:

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

在此处输入图像描述

如果我尝试sample为此任务使用函数:

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.281600 -0.038330 -0.002498 -0.001506  0.034380  0.288800

但是这个范围取决于数据框中的行数,并且随着大小的增加而减小。

> 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

我的问题是:

如何重新排列这样的数据集以获得给定的相关性(即 0.7)?(如果方法能消除对数据集大小的依赖也很好)

3个回答

这是一种基于生成额外随机数来重新排列数据的方法。

我们从具有特定相关性的双变量正态分布中抽取样本。接下来,我们计算我们获得的值的等级。这些等级用于对原始值进行排序。对于这种方法,我们对原始值进行顶级排序。xyxy

首先,我们创建实际的数据集(如您的示例中)。

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

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

现在,我们指定一个相关矩阵。

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

(对于两个变量)和指定相关性的二元正态分布生成随机数据。在 R 中,这可以通过包中的函数来完成我们用来表示相关性是经验相关性(而不是总体相关性)。μ=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

随机数据完全匹配指定的相关性。

接下来,我们计算随机数据的等级。

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

要对 中的原始数据使用排名d,我们必须对原始数据进行排序。

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

现在,我们可以使用排名来指定排序数据的顺序。

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

得到的相关性与指定的不完全匹配,但差异相对较小。

在这里,dx_sorted[rx]dy_sorted[ry]是原始数据的重新采样版本d

要生成具有指定相关性的两个均匀分布,Ruscio & Kaczetow (2008) 算法将起作用。他们提供R 代码然后,您可以使用简单的线性函数进行转换,以获得目标最小值、最大值、平均值和 SD。

Ruscio & Kaczetow 算法

我将总结双变量情况,但它也适用于多变量问题。不相关XoYo以任何形状(例如,统一)生成。然后,X1Y1生成为具有中间相关性的二元正态。X1Y1被替换为X0Y0以保持排名的方式。根据 r(X1,Y1) 太低或太高。X2Y2生成为具有新的中间相关性的二元正态。重复。

请注意,这与@Sven Hohenstein 的解决方案非常相似,只是它是迭代的,因此中间相关性将越来越接近目标相关性,直到它们无法区分。另外,请注意,此算法可用于生成较大的总体(例如,N=100 万)从中抽取较小的样本 - 如果您需要有抽样误差,这很有用。

对于相关帖子:相关性和非正态分布

保留描述性统计

无法保证该算法将产生完全相同的描述。但是,由于均匀分布的均值和 SD 由其最小值和最大值决定,您可以简单地调整最小值和最大值来修复所有问题。

XgYg是您从 Ruscio & Kaczetow 算法的最后一次迭代中生成的变量,XfYf成为您希望拥有的最终变量(带有目标描述),并且XY成为数据集中的原始变量。

计算 Xf=(Xgmin(X))(max(X)min(x))/(max(Xg)min(Xg))

做同样的事情Yf

参考:

Ruscio, J. 和 Kaczetow, W. (2008)。使用迭代算法模拟多元非正态数据。多元行为研究,43, 355–381。doi:10.1080/00273170802285693

我猜当您说“重新采样”时,您的意思是“模拟”,这更笼统。以下是我所知道的模拟具有指定相关性的正常双变量数据的最简洁方法。用您自己想要的值替换 r 和 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")