Как задать априорную корреляцию между выборками, выбранными случайным образом из двух полиномиальных распределений?

Рассмотрим следующую игру: в каждом испытании вам будут представлены 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?


person user1363251    schedule 26.07.2016    source источник
comment
Вы начинаете с красных и синих точек, и вдруг они становятся зелеными?   -  person EBH    schedule 26.07.2016
comment
хороший момент, извините за неряшливость.   -  person user1363251    schedule 26.07.2016
comment
Использовать связки? Отвечает ли это на ваш вопрос?   -  person nirvana-msu    schedule 26.07.2016


Ответы (1)


Обычно вы спрашиваете, как создать 2 вектора с заданной корреляцией, так что это больше статистика, чем вопрос программирования, но это можно сделать следующим образом:

шаг 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 можно заменить на любую функцию случайных сгенерированных чисел, например randi или randn, и, если требуется какое-то конкретное распределение, его можно получить используя его 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. Вот пример - сначала вывод, когда 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 не станет достаточно близким к тому, что вы хотите.

person EBH    schedule 26.07.2016
comment
@EBHTЭто почти идеально, я очень ценю. Могу я попросить два уточнения? Во-первых, можно ли настроить код так, чтобы x ›y в 50% испытаний и x‹ y для остальных испытаний? Во-вторых, мне кажется, что мне нужно по-другому указать матрицу R для отрицательных корреляций. Скажем, мне нужно соотношение - 0,8. Установка R = [1 -0,8; -0,8 1] дает значения, которые больше не находятся в диапазоне от 10 до 50. Есть идеи? - person user1363251; 27.07.2016
comment
еще раз спасибо за бесценную помощь. Кажется, не работает. В конце кода я добавил: Xy = x ›y; checkx = length (найти (Xy == 1)); Yx = y ›x; checky = length (найти (Yx == 1)); но checkx и checky очень разные, что указывает на то, что x не превосходит y в 50% попыток. Есть идеи, прежде чем я отредактирую свой первоначальный пост? - person user1363251; 27.07.2016
comment
Спасибо! Я думал об этой уловке. Использование datasample () после разложения Холецкого снижает корреляцию. Но проблема может быть решена путем перебора подвыборок для нахождения ближайшего r. Сейчас я отредактирую свой первоначальный пост, думаю, это взаимодействие будет полезно другим. - person user1363251; 27.07.2016
comment
@ user1363251 Я рад, что он помог вам, и, пожалуйста, подумайте о том, чтобы принять и / или проголосовать за этот ответ, чтобы будущие читатели знали об этом был полезен. - person EBH; 27.07.2016
comment
Я тщательно протестировал ваш код и обнаружил две проблемы. Я открою новую тему, чтобы решить эти проблемы и обобщить предложенный вами метод. Еще раз спасибо за бесценную помощь. - person user1363251; 29.07.2016