Sử dụng phân phối đồng đều để tạo các mẫu ngẫu nhiên tương quan trong R


8

[Về những câu hỏi gần đây tôi đang tìm cách tạo ra các vectơ ngẫu nhiên trong R và tôi muốn chia sẻ "nghiên cứu" đó như một câu hỏi và trả lời độc lập về một điểm cụ thể.]

Tạo dữ liệu ngẫu nhiên với tương quan có thể được thực hiện bằng cách sử dụng phân tách Cholesky của ma trận tương quan tại đây , như được phản ánh trên các bài viết trước đâytại đây .C=LLT

Các câu hỏi mà tôi muốn giải quyết là làm thế nào để sử dụng phân phối Uniform để tạo số ngẫu nhiên tương quan từ phân phối biên khác nhau trong R .


2
Có vẻ như bạn đã khám phá lại copula Gaussian, ví dụ như xem câu hỏi liên quan ở đây . Có nhiều công thức khác được sử dụng phổ biến, nhưng Gaussian khá thuận tiện và có thể khá phù hợp cho một số tình huống.
Glen_b -Reinstate Monica

Câu trả lời:


8

Vì câu hỏi là

"cách sử dụng phân phối Thống nhất để tạo các số ngẫu nhiên tương quan từ các phân phối biên khác nhau trong "R

và không chỉ các biến thiên ngẫu nhiên bình thường, câu trả lời trên không tạo ra các mô phỏng với tương quan dự định cho một cặp phân phối biên tùy ý trong .R

Lý do là vì, đối với hầu hết các cdf và , khi trong đó biểu thị cdf chuẩn thông thường.G Y cor ( X , Y ) cor ( G - 1 X ( Φ ( X ) , G - 1 Y ( Φ ( Y ) ) , ( X , Y ) ~ N 2 ( 0 , Σ ) , ΦGXGY

cor(X,Y)cor(GX1(Φ(X),GY1(Φ(Y)),
(X,Y)N2(0,Σ),
Φ

Nói một cách dí dỏm, đây là một ví dụ ngược với Exp (1) và Gamma (.2,1) là cặp phân phối biên của tôi trong .R

library(mvtnorm)
#correlated normals with correlation 0.7
x=rmvnorm(1e4,mean=c(0,0),sigma=matrix(c(1,.7,.7,1),ncol=2),meth="chol")
cor(x[,1],x[,2])
  [1] 0.704503
y=pnorm(x) #correlated uniforms
cor(y[,1],y[,2])
  [1] 0.6860069
#correlated Exp(1) and Ga(.2,1)
cor(-log(1-y[,1]),qgamma(y[,2],shape=.2))
  [1] 0.5840085

Một ví dụ ngược lại rõ ràng khác là khi là cdf Cauchy, trong trường hợp đó, mối tương quan không được xác định.GX

Để đưa ra một bức tranh rộng hơn, đây là một mã R trong đó cả và đều tùy ý:G YGXGY

etacor=function(rho=0,nsim=1e4,fx=qnorm,fy=qnorm){
  #generate a bivariate correlated normal sample
  x1=rnorm(nsim);x2=rnorm(nsim)
  if (length(rho)==1){
    y=pnorm(cbind(x1,rho*x1+sqrt((1-rho^2))*x2))
    return(cor(fx(y[,1]),fy(y[,2])))
    }
  coeur=rho
  rho2=sqrt(1-rho^2)
  for (t in 1:length(rho)){
     y=pnorm(cbind(x1,rho[t]*x1+rho2[t]*x2))
     coeur[t]=cor(fx(y[,1]),fy(y[,2]))}
  return(coeur)
  }

nhập mô tả hình ảnh ở đây

Chơi xung quanh với các cdf khác nhau đã khiến tôi phát hiện ra trường hợp đặc biệt này của phân phối cho và phân phối log-Normal cho : G X G Yχ32GXGY

rhos=seq(-1,1,by=.01)
trancor=etacor(rho=rhos,fx=function(x){qchisq(x,df=3)},fy=qlnorm)
plot(rhos,trancor,ty="l",ylim=c(-1,1))
abline(a=0,b=1,lty=2)

trong đó cho thấy khoảng cách từ đường chéo tương quan có thể được.

Cảnh báo cuối cùng Đưa ra hai phân phối tùy ý và , phạm vi giá trị có thể có của không nhất thiết . Vấn đề có thể không có giải pháp.G Y cor ( X , Y ) ( - 1 , 1 )GXGYcor(X,Y)(1,1)


Tuyệt diệu! Ty! Có cách nào để chúng ta có thể tìm thấy một phân đoạn gần đúng mà sự khởi hành không được đánh dấu, giống như trường hợp thông thường, vẫn hợp lý cho các ứng dụng thực tế không?
Antoni Parellada 04/05/2015

5

Tôi đã viết correlategói. Mọi người nói rằng nó rất hứa hẹn (xứng đáng được xuất bản trên Tạp chí Phần mềm Thống kê), nhưng tôi không bao giờ viết bài cho nó vì tôi chọn không theo đuổi sự nghiệp học thuật.

Tôi tin rằng correlategói không được duy trì vẫn còn trên CRAN.

Khi bạn cài đặt nó, bạn có thể làm như sau:

require('correlate')
a <- rnorm(100)
b <- runif(100)
newdata <- correlate(cbind(a,b),0.5)

Kết quả là newdata sẽ có tương quan 0,5, mà không thay đổi các phân phối đơn biến của ab(cùng các giá trị ở đó, chúng chỉ được di chuyển xung quanh cho đến khi đạt được tương quan đa biến 0,5.

Tôi sẽ trả lời các câu hỏi ở đây, xin lỗi vì thiếu tài liệu.


Bravo, đây là câu trả lời hoàn hảo! Bạn có cách nào để phát hiện các giá trị của mối tương quan không thể đạt tới không?
Tây An

@ Tây An Có một số điểm không thể, như một vài điểm dữ liệu và mối tương quan thực sự cụ thể được tìm kiếm mà không thể đạt được. ví dụ: chỉ có 3 giá trị được ghép nối.
PascalVKooten

Cũng lưu ý rằng có thể có nhiều hơn 2 biến, ví dụ: đối với 3 biến bạn có thể xác định ma trận tương quan 3x3, 4 biến 4 x 4.
PascalVKooten

Nói chung, nó sẽ hoạt động miễn là bạn không muốn điều đó là không thể, nhưng trước khi bạn làm việc nghiêm túc với nó, bạn nên thực hiện một vài lần chạy thử.
PascalVKooten

Những người quan tâm đến nó đã sử dụng dữ liệu thu nhập; vô số số không và phân phối gaussian-ish cho thu nhập khác không.
PascalVKooten

1
  1. Tạo hai mẫu dữ liệu tương quan từ phân phối ngẫu nhiên tiêu chuẩn thông thường theo mối tương quan được xác định trước .

    Ví dụ: hãy chọn một tương quan r = 0,7 và mã hóa một ma trận tương quan, chẳng hạn như:

    (C <- matrix(c(1,0.7,0.7,1), nrow = 2)) [,1] [,2] [1,] 1.0 0.7 [2,] 0.7 1.0

    Chúng ta có thể sử dụng mvtnormđể tạo ra hai mẫu này dưới dạng một vectơ ngẫu nhiên hai biến:

    set.seed(0)

    SN <- rmvnorm(mean = c(0,0), sig = C, n = 1e5)dẫn đến hai thành phần vector được phân phối là ~ và với a . Cả hai thành phần có thể được giải mã như sau:N(0,1)cor(SN[,1],SN[,2])= 0.6996197 ~ 0.7

    X1 <- SN[,1]; X2 <- SN[,2]

    Đây là cốt truyện với đường hồi quy chồng chéo:

  2. Sử dụng Biến đổi tích phân xác suất ở đây để thu được một vectơ ngẫu nhiên bivariate với các phân phối biên ~ và cùng một mối tương quan :U(0,1)

    U <- pnorm(SN)pnormSNerf(SN)Φ(SN)cor(U[,1], U[,2]) = 0.6816123 ~ 0.7

    Một lần nữa chúng ta có thể phân tách vectơ U1 <- U[,1]; U2 <- U[,2]và tạo ra một biểu đồ phân tán với các phân bố biên ở các cạnh, cho thấy rõ bản chất thống nhất của chúng:

  3. Áp dụng phương pháp lấy mẫu biến đổi nghịch đảo ở đây để cuối cùng thu được bivector của các điểm tương quan như nhau thuộc về bất kỳ họ phân phối nào chúng ta đặt ra để tái tạo.

    Từ đây, chúng ta có thể tạo ra hai vectơ phân phối bình thường và có phương sai bằng hoặc khác nhau . Ví dụ: Y1 <- qnorm(U1, mean = 8,sd = 10)Y2 <- qnorm(U2, mean = -5, sd = 4), sẽ duy trì mối tương quan mong muốn , cor(Y1,Y2) = 0.6996197 ~ 0.7.

    Hoặc chọn cho các bản phân phối khác nhau. Nếu các bản phân phối được chọn rất khác nhau, mối tương quan có thể không chính xác. Chẳng hạn, hãy U1theo dõi phân phối với 3 df và theo cấp số nhân với = 1: và The . Dưới đây là biểu đồ tương ứng:λtU2λZ1 <- qt(U1, df = 3)Z2 <- qexp(U2, rate = 1)cor(Z1,Z2) [1] 0.5941299 < 0.7

Dưới đây là một ví dụ về mã cho toàn bộ quá trình và các lề thông thường:

Cor_samples <- function(r, n, mean1, mean2, sd1, sd2){
C <- matrix(c(1,r,r,1), nrow = 2)
require(mvtnorm)
SN <- rmvnorm(mean = c(0,0), sig = C, n = n)
U <- pnorm(SN)
U1 <- U[,1]
U2 <- U[,2]

 Y1 <<- qnorm(U1, mean = mean1,sd = sd1) 
 Y2 <<- qnorm(U2, mean = mean2,sd = sd2) 

sample_measures <<- as.data.frame(c(mean(Y1), mean(Y2), sd(Y1), sd(Y2), cor(Y1,Y2)), names<-c("mean Y1", "mean Y2", "SD Y1", "SD Y2", "Cor(Y1,Y2)"))
sample_measures
}

Để so sánh, tôi đã kết hợp một hàm dựa trên phân tách Cholesky:

Cholesky_samples <- function(r, n, mean1, mean2, sd1, sd2){
C <- matrix(c(1,r,r,1), nrow = 2)
L <- chol(C)
X1 <- rnorm(n)
X2 <- rnorm(n)
X <- rbind(X1,X2)

Y <- t(L)%*%X
Y1 <- Y[1,]
Y2 <- Y[2,]

N_1 <<- Y[1,] * sd1 + mean1
N_2 <<- Y[2,] * sd2 + mean2

sample_measures <<- as.data.frame(c(mean(N_1), mean(N_2), sd(N_1), sd(N_2), cor(N_1, N_2)), 
                  names<-c("mean N_1", "mean N_2", "SD N_1", "SD N_2","cor(N_1,N_2)"))
sample_measures
}

Thử cả hai phương pháp để tạo các mẫu tương quan (giả sử, ) được phân phối ~ và mà chúng tôi nhận được, cài đặt :N ( 97 , 23 ) N ( 32 , 8 )r=0.7N(97,23)N(32,8)set.seed(99)

Sử dụng đồng phục:

cor_samples(0.7, 1000, 97, 32, 23, 8)
           c(mean(Y1), mean(Y2), sd(Y1), sd(Y2), cor(Y1, Y2))
mean Y1                                            96.5298821
mean Y2                                            32.1548306
SD Y1                                              22.8669448
SD Y2                                               8.1150780
cor(Y1,Y2)                                          0.7061308

và sử dụng Cholesky:

Cholesky_samples(0.7, 1000, 97, 32, 23, 8)
             c(mean(N_1), mean(N_2), sd(N_1), sd(N_2), cor(N_1, N_2))
mean N_1                                                   96.4457504
mean N_2                                                   31.9979675
SD N_1                                                     23.5255419
SD N_2                                                      8.1459100
cor(N_1,N_2)                                                0.7282176

Theo kinh nghiệm, có vẻ như khi bạn đi từ N (0,1) -> ~ Unif. -> ~ được phân phối theo các phân phối đã chọn, mối tương quan không thay đổi trừ khi phân phối cuối cùng khác biệt đáng kể so với N (0,1) ban đầu. Tôi đã bao gồm các giá trị ... Trong mọi trường hợp, bạn có thấy các vấn đề cụ thể với chính phương thức đó để áp dụng thực tế không? f ( F - 1 ( X ) )
F1(X)
f(F1(X))
Antoni Parellada

Tôi đã thay đổi hàm ở cuối câu trả lời để bao gồm mối tương quan của các mẫu được tính toán, để so sánh với số được cắm, và chúng dường như khớp với nhau.
Antoni Parellada

2
Liệu có vấn đề với ứng dụng thực tế hay không phụ thuộc vào ứng dụng thực tế; Đối với một số điều này là ổn. Lưu ý rằng vì các phép biến đổi là đơn điệu, nên các mối tương quan không theo tỷ lệ như Spearman's rho và Kendall's tau sẽ không bị thay đổi.
Glen_b -Reinstate Monica
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.