如何指定从两个多项分布中随机抽取的样本之间的先验相关性?

时间:2016-07-26 19:33:16

标签: python r matlab correlation multinomial

考虑以下游戏:在每个试验中,您将看到 x 红色和 y 蓝点。你必须决定是否有更多的红点而不是蓝点。对于每个试验,给定颜色的最小点数为10,最大值为50.红色和蓝色点遵循相同的多项分布(为简单起见,我们考虑每个整数在10到50之间出现的概率是相似的)。

我想建立300个试验。为此,我从每个多项分布中抽取300个样本。重要的是,我想指定(先验)来自第一个分布的300个样本与来自第二个分布的300个样本之间的相关性。我想在五对样本集中找到-0.8,-0.5,0,0.5和0.8的相关性。

优选地,我还想对这些集合进行采样,以便在每个集合(X,Y)中具有任何指定的相关性,X样本中的一半将大于Y(x(i) > y(i)),并且另一半将小于Y(x(i) < y(i))。

我怎么能在python,R或MATLAB中做到这一点?

1 个答案:

答案 0 :(得分:1)

基本上你问如何create 2 vectors with a specified correlation,所以它比编程问题更多的统计数据,但它可以通过以下方式完成:

第1步 - 创建具有所需相关性的两个向量

r = 0.75;                % r is the desired correlation
M = rand(10000,2);       % two vectors from uniform distribution between 0 to 1
R = [1 r; r 1];
L = chol(R);             % this is Cholesky decomposition of R
M = M*L;                 % when multiplied by M it gives the wanted correlation
M = (M+abs(min(M(:))));  % shift the vector to only positive values
M = M./max(M(:));        % normalize the vector...
M = round(40*M)+10;      % ...to values between 10 to 50
disp([min(M(:)) max(M(:))])
first_r = corr( M(:,1), M(:,2));      % and check the resulted correlation

rand函数可以更改为任意随机生成的数字函数,例如randirandn,如果需要某些特定的分布,则可以获取using the it's cdf

第2步 - 为两组样本采样这些向量,一组x> y,另一组y> x

x = M(:,1);
y = M(:,2);
Xy = x>y;                % logical index for all x > y
Yx = y>x;                % logical index for all y > x
xy1 = datasample([x(Xy) y(Xy)],150,'Replace',false); % make a 1/2 sample like Xy
xy2 = datasample([x(Yx) y(Yx)],150,'Replace',false); % make a 1/2 sample like Yx
x = [xy1(:,1);xy2(:,1)];           % concat the smaples back to x
y = [xy1(:,2);xy2(:,2)];           % concat the smaples back to y
checkx = sum(x>y)                  % how many times x is bigger than y
checky = sum(y>x)                  % how many times y is bigger than x
final_r = corr(x,y)                % and check the new correlation

第3步 - 纠正相关性

正如您所看到的,final_r与所需的r不同,所以为了获得它,您必须将第一个r移动距离final_r {1}}。这是一个示例 - 首先是r = 0.75时的输出:

    10    50
checkx =
   150
checky =
   150
final_r =
      0.67511

我们发现final_r向下移动了0.074886,因此我们希望将原始r向上移动此值以使我们的final_r正确。因此,如果我们使用r = 0.75+0.074886再次运行它,我们会得到:

    10    50
checkx =
   150
checky =
   150
final_r =
      0.76379

非常接近所需的r。我会在整个过程中运行一次循环,比如1000次以找到与所需的最近的r,或者只是设置一个继续搜索的阈值,直到final_r足够接近你想。