估算缺失数据,同时强制相关系数保持不变

时间:2016-09-21 13:55:39

标签: python r matlab julia

考虑以下(excel)数据集:

m   |   r
----|------
2.0 | 3.3
0.8 |   
    | 4.0
1.3 |   
2.1 | 5.2
    | 2.3
    | 1.9
2.5 | 
1.2 | 3.0
2.0 | 2.6

我的目标是使用以下条件填写缺失值:

  

将上述两列(约0.68)之间的成对相关性表示为R.将<*>表示为R *,填充空单元格后 填写表格,使(R - R *)^ 2 = 0 。这就是说,我想保持数据的相关结构不变。

到目前为止,我已经使用Matlab完成了它:

clear all;

m = xlsread('data.xlsx','A2:A11') ;
r = xlsread('data.xlsx','B2:B11') ;

rho = corr(m,r,'rows','pairwise');

x0 = [1,1,1,1,1,1];
lb = [0,0,0,0,0,0];
f = @(x)my_correl(x,rho);

SOL = fmincon(f,x0,[],[],[],[],lb)

函数my_correl是:

function X = my_correl(x,rho)

sum_m = (11.9 + x(1) + x(2) + x(3));
sum_r = (22.3 + x(1) + x(2) + x(3));
avg_m = (11.9 + x(1) + x(2) + x(3))/8;
avg_r = (22.3 + x(4) + x(5) + x(6))/8;
rho_num = 8*(26.32 + 4*x(1) + 2.3*x(2) + 1.9*x(3) + 0.8*x(4) + 1.3*x(5) + 2.5*x(6)) - sum_m*sum_r;
rho_den = sqrt(8*(22.43 + (4*x(1))^2 + (2.3*x(2))^2 + (1.9*x(3))^2) - sum_m^2)*sqrt(8*(78.6 + (0.8*x(4))^2 + (1.3*x(5))^ + (2.5*x(6))^2) - sum_r^2);

X = (rho - rho_num/rho_den)^2;

end

此函数手动计算相关性,其中每个缺失的数据都是变量x(i)

问题:我的实际数据集有超过20,000个观察结果。我无法手动创建该rho公式。

如何填写我的数据集?

注1:我愿意使用Python,Julia或R. Matlab等替代语言,它只是我的默认语言。

注2:答案将获得100分的奖励。从现在起承诺。

1 个答案:

答案 0 :(得分:5)

这是我接近它的方式,提供R中的实现:

没有用于输入缺失数据点的唯一解决方案,使得完整(插补)数据的成对相关性等于不完整数据的成对相关性。所以要找到一个好的&#39;解决方案,而不仅仅是“任何&#39;在解决方案中,我们可以引入一个额外的标准,即完整的插补数据也应该与原始数据共享相同的线性回归。这导致我们采用一种相当简单的方法。

  1. 计算原始数据的线性回归模型。
  2. 找到错误值的估算值,这些值恰好位于此回归线上。
  3. 为此回归线周围的估算值生成残差的随机散布
  4. 缩放估算残差以强制完整估算数据的相关性等于原始数据的相关性
  5. R中的解决方案:

    fit.comp = lm(r.comp ~ m.comp, data=dt)
    plot(dt$m.comp, dt$r.comp)
    points(dt$m, dt$r, col="red")
    abline(fit1, col="green")
    abline(fit.comp, col="blue")
    mtext(paste(" Rho =", round(rho,5)), at=-1)
    mtext(paste(" Rho2 =", round(rho2, 5)), at=6)
    

    作为最终检查,计算完整插补数据的线性回归 并绘制以显示回归线与原始数据相同。请注意,下图是针对下面显示的大数据集,以演示此方法在大数据上的使用。

    dt=structure(list(m = c(2, 0.8, NA, 1.3, 2.1, NA, NA, 2.5, 1.2, 2), 
                      r = c(3.3, NA, 4, NA, 5.2, 2.3, 1.9, NA, 3, 2.6)), 
                 .Names = c("m", "r"), row.names = c(NA, -10L), 
                 class = c("data.table", "data.frame"))
    

    enter image description here

    数据

    来自OP示例的原始玩具数据:

    dt = data.table(m=rnorm(1e5, 3, 2))[, r:=1.5 + 1.1*m + rnorm(1e5,0,2)]
    dt[sample(.N, 3e4), m:=NA]
    dt[sample(which(!is.na(m)), 3e4), r := NA]
    

    用于演示大数据的更大数据集

    =SUBSTITUTE(A1,CHOOSE(RANDBETWEEN(1,2),"wishes ","greetings "),"")