Як переставити 2D дані, щоб отримати відповідність?


9

У мене є такий простий набір даних з двома безперервними змінними; тобто:

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)? (Буде також добре, якщо метод зніме залежність від розміру набору даних)

Відповіді:


6

Ось один із способів переставити дані, засновані на генерації додаткових випадкових чисел.

Ми витягуємо зразки з двовимірного нормального розподілу із заданою кореляцією. Далі ми обчислюємо ранги отриманих значень і . Ці ранги використовуються для впорядкування вихідних значень. Для цього підходу ми маємо верхнє сортування як початкових значень і .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.


2
+1 Це досить круто. Етапи: 1) генерувати нормальні дані при правильній кореляції Пірсона; Чому це працює? Чи є аналітичний результат, який говорить про це? Обмеження нерівностей, що підтримують різні заходи кореляції близькими один до одного для добре розроблених розподілів чи чогось іншого?
Білл

1
@Bill Я не можу пояснити підхід аналітично. Це просто ідея, яка мені прийшла в голову. Однак ви добре підсумували кроки. Дякую.
Свен Гогенштайн

2

Для створення двох рівномірних розподілів із заданим співвідношенням буде працювати алгоритм Ruscio & Kaczetow (2008). Вони забезпечують R - код . Потім ви можете перетворити за допомогою простої лінійної функції, щоб отримати цільові min, max, mean та SD.

Алгоритм Русіо і Качтеу

Я підсумую біваріантний випадок, але він також може працювати з багатовимірними проблемами. Некорельовані та генеруються з будь-якою формою (наприклад, рівномірною). Тоді і генеруються як біваріантні нормальні з проміжною кореляцією. і замінюються і відповідно до збереження рангу. Відрегулюйте проміжну кореляцію, щоб бути вищою або нижчою залежно від того занадто низький або занадто високий r ( ). З новим проміжним співвідношенням і генеруються як біваріантні нормальні . Повторіть.XoYoX1Y1X1Y1X0Y0X1,Y1X2Y2

Зауважте, що це дуже схоже на рішення @Sven Hohenstein, за винятком того, що воно є ітераційним, тому проміжна кореляція буде наближатися до націленої кореляції, поки їх не відрізнити. Також зауважте, що цей алгоритм можна використовувати для генерації великої сукупності (наприклад, N = 1 мільйон), з якої можна взяти менші зразки - це корисно, якщо вам потрібно помилка вибірки.

Для пов’язаної посади: Кореляція та ненормальні розподіли

Збереження описової статистики

Немає гарантії, що алгоритм дасть такі самі описи. Однак, оскільки середнє значення рівномірного розподілу та SD визначаються його min та max, ви можете просто налаштувати min та max, щоб все виправити.

Нехай і це ваші згенеровані змінні з останньої ітерації алгоритму Ruscio & Kaczetow, і - ваші остаточні змінні, які ви сподіваєтесь мати (з цільовими описовими ), а і - ваші вихідні змінні у вашому наборі даних. XgYgXfYfXY

Обчисліть Xf=(Xgmin(X))(max(X)min(x))/(max(Xg)min(Xg))

Зробіть те саме дляYf

Довідка:

Ruscio, J., & Kaczetow, W. (2008). Моделювання багатоваріантних ненормальних даних за допомогою ітеративного алгоритму. Багатовимірне поведінкове дослідження, 43, 355–381. doi: 10.1080 / 00273170802285693


1

Я здогадуюсь, що, коли ви говорите "переутворювати", ви маєте на увазі "імітувати", що є більш загальним. Нижче наведено найбільш стислий спосіб, який я знаю, щоб імітувати нормальні, біваріантні дані із заданим співвідношенням. Підставити власні бажані значення для 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")

3
Ні, я насправді маю на увазі "повторний вибір". Мені потрібно тримати постійні засоби та іншу описову статистику (sd, min, max) обох змінних. Оновлено питання.
Юрій Петровський
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.