Tạo một biến ngẫu nhiên có tương quan xác định với (các) biến hiện có


71

Đối với một nghiên cứu mô phỏng tôi phải tạo ra các biến ngẫu nhiên cho thấy mối tương quan (dân số) được bắt đầu với một biến hiện có .Y

Tôi đã xem xét các Rgói copulaCDVinecó thể tạo ra các phân phối đa biến ngẫu nhiên với cấu trúc phụ thuộc nhất định. Tuy nhiên, không thể sửa một trong các biến kết quả thành một biến hiện có.

Bất kỳ ý tưởng và liên kết đến các chức năng hiện có được đánh giá cao!


Kết luận: Hai câu trả lời hợp lệ được đưa ra, với các giải pháp khác nhau:

  1. Một R tập lệnh của caracal, tính toán một biến ngẫu nhiên có tương quan (mẫu) chính xác với một biến được xác định trước
  2. Một R hàm tôi tự tìm thấy, tính toán một biến ngẫu nhiên có tương quan dân số được xác định với một biến được xác định trước

Bổ sung [@ttnphns ': Tôi đã tự do mở rộng tiêu đề câu hỏi từ trường hợp biến cố định duy nhất sang số lượng biến cố định tùy ý; tức là làm thế nào để tạo một biến có các sửa lỗi được xác định trước với một số biến cố định, hiện có]


2
Xem thống kê câu hỏi liên quan này.stackexchange.com/questions/13382/ mà trực tiếp giải quyết câu hỏi của bạn (ít nhất là khía cạnh lý thuyết của nó).
Macro

Câu trả lời:


56

Đây là một số khác: đối với các vectơ có giá trị trung bình 0, tương quan của chúng bằng cosin của góc của chúng. Vì vậy, một cách để tìm một vectơ với chính xác tương quan mong muốn , tương ứng với một góc :r θxrθ

  1. lấy vectơ cố định và vectơ ngẫu nhiênx 2x1x2
  2. căn giữa cả hai vectơ (trung bình 0), cho vectơ , ˙ x 2x˙1x˙2
  3. tạo trực giao thành (chiếu lên không gian con trực giao), cho ˙ x 1 ˙ x 2x˙2x˙1x˙2
  4. scale và thành chiều dài 1, cho và ˙ x 2 ˉ x 1 ˉ x 2x˙1x˙2x¯1x¯2
  5. ˉ x 1θ ˉ x 1rx1x¯2+(1/tan(θ))x¯1 là vectơ có góc tới là và có tương quan với do đó là . Đây cũng là mối tương quan với vì các phép biến đổi tuyến tính giữ nguyên mối tương quan.x¯1θx¯1rx1

Đây là mã:

n     <- 20                    # length of vector
rho   <- 0.6                   # desired correlation = cos(angle)
theta <- acos(rho)             # corresponding angle
x1    <- rnorm(n, 1, 1)        # fixed given data
x2    <- rnorm(n, 2, 0.5)      # new random data
X     <- cbind(x1, x2)         # matrix
Xctr  <- scale(X, center=TRUE, scale=FALSE)   # centered columns (mean 0)

Id   <- diag(n)                               # identity matrix
Q    <- qr.Q(qr(Xctr[ , 1, drop=FALSE]))      # QR-decomposition, just matrix Q
P    <- tcrossprod(Q)          # = Q Q'       # projection onto space defined by x1
x2o  <- (Id-P) %*% Xctr[ , 2]                 # x2ctr made orthogonal to x1ctr
Xc2  <- cbind(Xctr[ , 1], x2o)                # bind to matrix
Y    <- Xc2 %*% diag(1/sqrt(colSums(Xc2^2)))  # scale columns to length 1

x <- Y[ , 2] + (1 / tan(theta)) * Y[ , 1]     # final new vector
cor(x1, x)                                    # check correlation = rho

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

Đối với phép chiếu trực giao , tôi đã sử dụng phân tách để cải thiện tính ổn định số, từ đó chỉ đơn giản là .Q R P = Q Q 'PQRP=QQ


Tôi đã cố gắng viết lại mã thành cú pháp SPSS. Tôi vấp phải sự phân tách QR của bạn, trả về cột 20x1. Trong SPSS tôi có chuẩn hóa Gram-Schmidt (cũng là phân tách QR) nhưng không thể sao chép cột Q kết quả của bạn. Bạn có thể nhai lại hành động QR của bạn với tôi không? Hoặc chỉ ra một số công việc xung quanh để có được chiếu. Cảm ơn.
ttnphns

@caracal, P <- X %*% solve(t(X) %*% X) %*% t(X)không tạo ra r = 0,6, vì vậy đó không phải là vấn đề. Tôi vẫn còn bối rối. (Tôi rất vui khi bắt chước biểu hiện của bạn Q <- qr.Q(qr(Xctr[ , 1, drop=FALSE]))trong SPSS nhưng không biết làm thế nào.)
ttnphns

@ttnphns Xin lỗi vì sự nhầm lẫn, nhận xét của tôi là cho trường hợp chung. Áp dụng nó vào tình huống trong ví dụ: Lấy ma trận chiếu thông qua phân tách QR chỉ để ổn định số. Bạn có thể nhận được ma trận chiếu như nếu không gian con được kéo dài bởi các cột của ma trận . Trong R, bạn có thể viết ở đây vì không gian con được kéo dài bởi cột đầu tiên của . Ma trận cho phép chiếu lên phần bù trực giao là IP. XP=X(XX)1XXXctr[ , 1] %*% solve(t(Xctr[ , 1]) %*% Xctr[ , 1]) %*% t(Xctr[ , 1])Xctr
caracal

4
Bất cứ ai cũng có thể làm rõ làm thế nào để thực hiện một cái gì đó tương tự cho nhiều hơn chỉ hai mẫu? Nói, nếu tôi muốn 3 mẫu tương quan theo cặp với rho, làm thế nào tôi có thể chuyển đổi giải pháp này để đạt được điều đó?
Andre Terra

đối với trường hợp giới hạn rho=1tôi thấy nó hữu ích để làm một cái gì đó như thế này: if (isTRUE(all.equal(rho, 1))) rho <- 1-10*.Machine$double.eps, nếu không tôi đã nhận được NaNs
PatrickT

19

Tôi sẽ mô tả các giải pháp chung nhất có thể. Giải quyết vấn đề theo tính tổng quát này cho phép chúng tôi đạt được một triển khai phần mềm nhỏ gọn đáng chú ý: chỉ cần hai dòng Rmã ngắn .

Chọn một vectơ , có cùng độ dài với , theo bất kỳ phân phối nào bạn muốn. Hãy là dư của các hình vuông hồi quy nhất của so với : đây trích xuất thành phần từ . Bằng cách thêm lại một bội số phù hợp của để , chúng tôi có thể tạo ra một vector có bất kỳ mong muốn tương quan với . Lên đến một hằng số cộng gộp tùy ý và hằng số nhân dương - mà bạn có thể tự do lựa chọn theo bất kỳ cách nào - giải pháp làY Y X Y Y X Y Y ρ YXYYXYYXYYρY

XY;ρ=ρSD(Y)Y+1ρ2SD(Y)Y.

(" " là viết tắt của mọi phép tính tỷ lệ với độ lệch chuẩn.)SD


Đây là Rmã làm việc . Nếu bạn không cung cấp , mã sẽ rút ra các giá trị của nó từ phân phối chuẩn chuẩn đa biến.X

complement <- function(y, rho, x) {
  if (missing(x)) x <- rnorm(length(y)) # Optional: supply a default if `x` is not given
  y.perp <- residuals(lm(x ~ y))
  rho * sd(y.perp) * y + y.perp * sd(y) * sqrt(1 - rho^2)
}

Để minh họa, tôi đã tạo một ngẫu nhiên với thành phần và tạo ra có các mối tương quan được chỉ định khác nhau với này . Tất cả chúng đều được tạo với cùng một vectơ bắt đầu . Dưới đây là những phân tán của họ. Các "tấm thảm" ở dưới cùng của mỗi bảng hiển thị vectơ chung .50 X Y ; ρ Y X = ( 1 , 2 , ... , 50 )Y50XY;ρYX=(1,2,,50)Y

Nhân vật

Có một sự tương đồng đáng chú ý giữa các lô, không có :-).


Nếu bạn muốn thử nghiệm, đây là mã tạo ra những dữ liệu và hình này. (Tôi không bận tâm sử dụng quyền tự do để thay đổi và chia tỷ lệ kết quả, đây là những thao tác dễ dàng.)

y <- rnorm(50, sd=10)
x <- 1:50 # Optional
rho <- seq(0, 1, length.out=6) * rep(c(-1,1), 3)
X <- data.frame(z=as.vector(sapply(rho, function(rho) complement(y, rho, x))),
                rho=ordered(rep(signif(rho, 2), each=length(y))),
                y=rep(y, length(rho)))

library(ggplot2)
ggplot(X, aes(y,z, group=rho)) + 
  geom_smooth(method="lm", color="Black") + 
  geom_rug(sides="b") + 
  geom_point(aes(fill=rho), alpha=1/2, shape=21) +
  facet_wrap(~ rho, scales="free")

BTW, phương pháp này dễ dàng khái quát hóa cho nhiều hơn một : nếu có thể về mặt toán học, nó sẽ tìm thấy một có các mối tương quan được chỉ định với toàn bộ bộ . Chỉ cần sử dụng bình phương tối thiểu thông thường để loại bỏ các hiệu ứng của tất cả từ và tạo thành một tổ hợp tuyến tính phù hợp của và phần dư. (Nó giúp thực hiện điều này trên cơ sở kép cho , thu được bằng cách tính toán nghịch đảo giả. Mã follownig sử dụng SVD của để thực hiện điều đó.)Y Y i Y i X Y i Y YXY1,Y2,,Yk;ρ1,ρ2,,ρkYiYiXYiYY

Đây là bản phác thảo của thuật toán R, trong đó được đưa ra dưới dạng các cột của ma trận :Yiy

y <- scale(y)             # Makes computations simpler
e <- residuals(lm(x ~ y)) # Take out the columns of matrix `y`
y.dual <- with(svd(y), (n-1)*u %*% diag(ifelse(d > 0, 1/d, 0)) %*% t(v))
sigma2 <- c((1 - rho %*% cov(y.dual) %*% rho) / var(e))
return(y.dual %*% rho + sqrt(sigma2)*e)

Sau đây là một triển khai đầy đủ hơn cho những người muốn thử nghiệm.

complement <- function(y, rho, x) {
  #
  # Process the arguments.
  #
  if(!is.matrix(y)) y <- matrix(y, ncol=1)
  if (missing(x)) x <- rnorm(n)
  d <- ncol(y)
  n <- nrow(y)
  y <- scale(y) # Makes computations simpler
  #
  # Remove the effects of `y` on `x`.
  #
  e <- residuals(lm(x ~ y))
  #
  # Calculate the coefficient `sigma` of `e` so that the correlation of
  # `y` with the linear combination y.dual %*% rho + sigma*e is the desired
  # vector.
  #
  y.dual <- with(svd(y), (n-1)*u %*% diag(ifelse(d > 0, 1/d, 0)) %*% t(v))
  sigma2 <- c((1 - rho %*% cov(y.dual) %*% rho) / var(e))
  #
  # Return this linear combination.
  #
  if (sigma2 >= 0) {
    sigma <- sqrt(sigma2) 
    z <- y.dual %*% rho + sigma*e
  } else {
    warning("Correlations are impossible.")
    z <- rep(0, n)
  }
  return(z)
}
#
# Set up the problem.
#
d <- 3           # Number of given variables
n <- 50          # Dimension of all vectors
x <- 1:n         # Optionally: specify `x` or draw from any distribution
y <- matrix(rnorm(d*n), ncol=d) # Create `d` original variables in any way
rho <- c(0.5, -0.5, 0)          # Specify the correlations
#
# Verify the results.
#
z <- complement(y, rho, x)
cbind('Actual correlations' = cor(cbind(z, y))[1,-1],
      'Target correlations' = rho)
#
# Display them.
#
colnames(y) <- paste0("y.", 1:d)
colnames(z) <- "z"
pairs(cbind(z, y))

Đây thực sự là một giải pháp tốt đẹp. Tuy nhiên, tôi đã thất bại trong việc tự mở rộng nó thành nhiều biến (biến cố định, trong câu trả lời của bạn). , bạn yêu cầu. Bạn có thể chứng minh điều đó? Xin vui lòng, với mã chú thích có thể đọc được bởi người dùng không phải R? YBTW, this method readily generalizes to more... Just use ordinary least squares... and form a suitable linear combination
ttnphns

1
@ttnphns Mình đã làm như vậy.
whuber

1
Cảm ơn bạn rất nhiều! Tôi hiểu rồi, và tôi đã mã hóa cách tiếp cận của bạn ngày hôm nay trong SPSS cho chính tôi. Đề nghị thực sự tuyệt vời của bạn. Tôi chưa bao giờ nghĩ về khái niệm cơ sở kép là có thể áp dụng để giải quyết nhiệm vụ.
ttnphns

Có thể sử dụng một cách tiếp cận tương tự để đưa ra một vectơ phân bố đồng đều? Đó là, tôi có một vectơ hiện có xvà muốn tạo một vectơ mới ytương quan với xnhưng cũng muốn yvectơ được phân phối đồng đều.
Skumin

@Skumin Cân nhắc sử dụng copula cho điều đó để bạn có thể kiểm soát mối quan hệ giữa hai vectơ.
whuber

6

Đây là một cách tiếp cận tính toán khác (giải pháp được điều chỉnh từ một bài đăng trên diễn đàn của Enrico Schumann). Theo Wolfgang (xem bình luận), đây là tính toán giống hệt với giải pháp được đề xuất bởi ttnphns.

Trái ngược với giải pháp của caracal, nó không tạo ra một mẫu có tương quan chính xác là , nhưng hai vectơ có tương quan dân số bằng .ρρρ

Hàm sau có thể tính toán phân phối mẫu bivariate được rút ra từ dân số với . Nó hoặc tính hai biến ngẫu nhiên hoặc lấy một biến hiện có (được truyền dưới dạng tham số ) và tạo biến thứ hai với tương quan mong muốn:ρx

# returns a data frame of two variables which correlate with a population correlation of rho
# If desired, one of both variables can be fixed to an existing variable by specifying x
getBiCop <- function(n, rho, mar.fun=rnorm, x = NULL, ...) {
     if (!is.null(x)) {X1 <- x} else {X1 <- mar.fun(n, ...)}
     if (!is.null(x) & length(x) != n) warning("Variable x does not have the same length as n!")

     C <- matrix(rho, nrow = 2, ncol = 2)
     diag(C) <- 1

     C <- chol(C)

     X2 <- mar.fun(n)
     X <- cbind(X1,X2)

     # induce correlation (does not change X1)
     df <- X %*% C

     ## if desired: check results
     #all.equal(X1,X[,1])
     #cor(X)

     return(df)
}

Hàm cũng có thể sử dụng các phân phối biên không bình thường bằng cách điều chỉnh tham số mar.fun. Tuy nhiên, lưu ý rằng việc sửa một biến chỉ có vẻ hoạt động với một biến được phân phối bình thường x! (có thể liên quan đến nhận xét của Macro).

Cũng lưu ý rằng "hệ số hiệu chỉnh nhỏ" từ bài đăng gốc đã bị xóa vì nó dường như làm sai lệch các mối tương quan kết quả, ít nhất là trong trường hợp phân phối Gaussian và tương quan Pearson (cũng xem bình luận).


Có vẻ như đây chỉ là một giải pháp gần đúng, nghĩa là, mối tương quan theo kinh nghiệm không chính xác bằng . Hay tôi đang thiếu một cái gì đó? ρ
caracal

1
Thật dễ dàng để chỉ ra rằng, ngoại trừ "sự điều chỉnh nhỏ đối với rho" (mục đích của nó trong bối cảnh này đã vượt qua tôi), điều này hoàn toàn giống với những gì ttnphns đề xuất trước đó. Phương pháp này chỉ đơn giản dựa trên phân tách Choleski của ma trận tương quan để thu được ma trận biến đổi mong muốn. Xem, ví dụ: en.wikipedia.org/wiki/ . Và vâng, điều này sẽ chỉ cung cấp cho bạn hai vectơ có tương quan dân số bằng rho.
Wolfgang

"Hiệu chỉnh nhỏ cho rho" là trong bài viết gốc và được mô tả ở đây . Thật ra, tôi không thực sự hiểu nó; nhưng một cuộc điều tra về 50000 tương quan mô phỏng với rho = .3 cho thấy nếu không có "hiệu chỉnh nhỏ", trung bình của r .299 được tạo ra, trong khi với hiệu chỉnh trung bình là .312 (là giá trị của rho đã hiệu chỉnh) là sản xuất. Vì vậy, tôi loại bỏ phần đó khỏi chức năng.
Felix S

Tôi biết điều này đã cũ, nhưng tôi cũng muốn lưu ý rằng phương pháp này sẽ không hoạt động đối với các ma trận tương quan xác định không tích cực. Ví dụ - một mối tương quan của -1.
zzk

1
Cảm ơn; Tôi nhận thấy rằng nếu x1 không chuẩn trung bình = 0, sd = 1, và bạn không muốn rescale nó, bạn sẽ cần phải sửa đổi dòng: X2 <- mar.fun(n)để X2 <- mar.fun(n,mean(x),sd(x))để có được mối tương quan mong muốn giữa x1 và x2
Dave M

6

Đặt là biến cố định của bạn và bạn muốn tạo biến tương quan với theo số lượng . Nếu được chuẩn hóa thì (vì là hệ số beta trong hồi quy đơn giản) , trong đó là biến ngẫu nhiên từ phân phối bình thường có nghĩa là và . Mối tương quan quan sát giữa dữ liệu và sẽ xấp xỉ ; và có thể được xem là các mẫu ngẫu nhiên từ dân số bình thường bivariate (nếuY X r X r Y = r X + E E 0 sd = XYXrXrY=rX+EE0 XYrXYXρ=rsd=1r2XYrXYX là từ bình thường) với .ρ=r

Bây giờ, nếu bạn muốn đạt được sự tương quan trong mẫu hai biến của bạn chính xác , bạn cần cung cấp mà có không tương quan với . Việc thắt chặt nó về 0 có thể đạt được bằng cách sửa đổi lặp đi lặp lại. Chà, chỉ với hai biến, một biến đã cho ( ) và một biến ( ), số lần lặp đủ thực sự là 1, nhưng với nhiều biến đã cho ( ) sẽ cần.rEXEXYX1,X2,X3,...

Cần lưu ý rằng nếu bình thường thì trong quy trình đầu tiên ("gần đúng ") cũng sẽ bình thường; tuy nhiên, trong phép nối lặp lại với "chính xác " có khả năng mất tính quy tắc bởi vì giá trị trường hợp khai thác phù hợp có chọn lọc.XrYYrY


Cập nhật ngày 11 tháng 11 năm 2017. Hôm nay tôi đã bắt gặp chủ đề cũ này và quyết định mở rộng câu trả lời của mình bằng cách hiển thị thuật toán của phép lặp lặp mà tôi đang nói lúc đầu.

Dưới đây là một giải pháp lặp làm thế nào để huấn luyện một biến ngẫu nhiên hoặc biến đổi ngẫu nhiên để tương quan hoặc phối hợp chính xác như chúng ta mong muốn (hoặc rất gần với số lần lặp phụ thuộc) với một tập hợp các biến cho (những biến này không thể sửa đổi).Y X

Disclamer: Giải pháp lặp này tôi đã thấy kém hơn so với giải pháp xuất sắc dựa trên việc tìm kiếm cơ sở képđược đề xuất bởi @whuber trong chủ đề này ngày hôm nay. Giải pháp của @ whuber không lặp lại và quan trọng hơn đối với tôi, nó dường như ảnh hưởng đến các giá trị của biến "pig" đầu vào ít hơn thuật toán "của tôi" (đó sẽ là một tài sản nếu nhiệm vụ là "chính xác" biến hiện có và không tạo ra phương sai ngẫu nhiên từ đầu). Tuy nhiên, tôi đang xuất bản của tôi vì tò mò và bởi vì nó hoạt động (xem thêm chú thích).

Vì vậy, chúng tôi đã đưa ra (đã sửa) các biến và biến chỉ là "lợn" được tạo ngẫu nhiên hoặc là biến dữ liệu tồn tại mà chúng tôi cần "sửa" - để mang lại chính xác với các mối tương quan (hoặc có thể là hiệp phương sai) với s. Tất cả dữ liệu phải liên tục; nói cách khác, cần có nhiều giá trị độc đáo.X1,X2,...,XmYYr1,r2,...,rmX

Ý tưởng: thực hiện lặp lại phù hợp của phần dư. Biết được mối tương quan (mục tiêu) mong muốn / hiệp phương sai, chúng ta có thể tính toán các giá trị dự đoán cho bằng cách sử dụng s dưới dạng nhiều dự đoán tuyến tính. Sau khi có được số dư ban đầu (từ hiện tại và dự đoán lý tưởng), hãy huấn luyện chúng lặp đi lặp lại không tương quan với các yếu tố dự đoán. Cuối cùng, lấy lại với phần dư. (Quy trình này là phát minh thử nghiệm của riêng tôi về bánh xe từ nhiều năm trước khi tôi không biết lý thuyết nào; tôi đã mã hóa nó sau đó trong SPSS.)YXYY

  1. Chuyển đổi mục tiêu s thành tổng của các sản phẩm chéo bằng cách nhân chúng với : . ( là chỉ số biến )rdf=n1Sj=rjdfjX

  2. Z chuẩn hóa tất cả các biến (tập trung vào từng biến, sau đó chia cho độ lệch st được tính trên đó ). và s là tiêu chuẩn. Tổng các hình vuông được quan sát hiện đang có = .dfYXdf

  3. Tính toán hệ số regressional dự đoán bằng s theo mục tiêu s: .YXrb=(XX)1S

  4. Tính toán các giá trị dự đoán cho : .YY^=Xb

  5. Tính số dư .E=YY^

  6. Tính tổng bình phương (mục tiêu) cần thiết cho số dư: .SSS=dfSSY^

  7. (Bắt đầu lặp lại.) Tính tổng các sản phẩm chéo được quan sát giữa hiện tại và mọi :EXjCj=i=1nEiXij

  8. Các giá trị chính xác của nhằm mục đích đưa tất cả s về gần ( là chỉ số trường hợp):EC0i

    Ei[corrected]=Eij=1mCjXijnj=1mXij2

    (mẫu số không thay đổi trên các lần lặp, tính toán trước)

    Hoặc, thay vào đó, một công thức hiệu quả hơn bảo đảm giá trị trung bình của trở thành . Đầu tiên, làm trung tâm ở mỗi lần tính toán trước của s ở bước 7, sau đó ở bước 8 này đúng như sau:E0 EC

    Ei[corrected]=Eij=1mCjXij3i=1nXij2j=1mXij2

    (một lần nữa, mẫu số được biết trước)1

  9. Đưa về giá trị đích của nó:SSEEi[corrected]=EiSSS/SSE

    Đến bước 7. (Đỗ, nói, 10-20 lặp; càng lớn là . Các bước lặp hơn có thể là cần thiết Nếu mục tiêu s là thực tế, là tích cực, và nếu cỡ mẫu không phải là quá ít, lặp đi lặp lại luôn trực tiếp để hội tụ. Kết thúc lặp lại.)mrSSSn

  10. Sẵn sàng: Tất cả các gần như bằng 0, điều đó có nghĩa là phần dư đã được đào tạo để khôi phục mục tiêu s. Tính toán phù hợp : .CErYY[corrected]=Y^+E

  11. thu được gần như được chuẩn hóa. Như một nét vẽ cuối cùng, bạn có thể muốn chuẩn hóa nó một cách chính xác, một lần nữa giống như bạn đã làm nó ở bước 2.Y

  12. Bạn có thể cung cấp cho bất kỳ phương sai nào và có nghĩa là bạn thích. Trên thực tế, trong số bốn thống kê - tối thiểu , tối đa , trung bình , st. dev . - bạn có thể chọn bất kỳ hai giá trị nào và biến đổi tuyến tính biến để nó hiển thị chúng mà không làm thay đổi s (tương quan) mà bạn đạt được (tất cả được gọi là thay đổi tỷ lệ tuyến tính).Yr

Để cảnh báo một lần nữa những gì đã nói ở trên. Với việc kéo chính xác đến , đầu ra không phải phân phối bình thường.YrY


1 Công thức hiệu chỉnh có thể tinh vi hơn nữa, ví dụ, để đảm bảo tính đồng nhất lớn hơn (tính theo tổng bình phương) của với mọi , đồng thời với việc đạt được các mối tương quan, - Tôi đã thực hiện một mã cho điều đó quá. (Tôi không biết nếu như "kép" nhiệm vụ là có thể giải quyết thông qua một gọn gàng hơn - noniterative - cách tiếp cận như của whuber .)YX


1
Cảm ơn câu trả lời của bạn. Đó là một giải pháp thực nghiệm / lặp đi lặp lại mà tôi đã nghĩ đến. Tuy nhiên, đối với các mô phỏng của tôi, tôi cần một giải pháp phân tích hơn mà không cần một thủ tục phù hợp tốn kém. May mắn thay, tôi vừa tìm thấy một giải pháp mà tôi sẽ đăng ngay ...
Felix S

Điều này hoạt động để tạo các quy tắc bivariate nhưng không hoạt động cho một phân phối tùy ý (hoặc bất kỳ phân phối không 'đáng tin cậy' nào)
Macro

1
Tôi không thấy lý do tại sao bạn đề xuất lặp lại khi bạn có thể sản xuất toàn bộ hình nón của các giải pháp. Có một số mục đích đặc biệt cho phương pháp này?
whuber

1
Chỉnh sửa mới nhất của bạn: Vì tôi cung cấp một công thức đơn giản cho tất cả các giải pháp, người ta có thể đạt được bất kỳ mục tiêu mong muốn nào, chẳng hạn như "tính đồng nhất lớn hơn" bằng cách giảm thiểu một hàm mục tiêu phù hợp trên tập hợp tất cả các giải pháp. Cách tiếp cận hoàn toàn chung chung. Bằng cách mở rộng biến (hoặc biến) thành cơ sở trực giao và khai thác tính bất biến tỷ lệ của mối tương quan, vấn đề trở thành một trong việc tối ưu hóa một hàm được xác định trên một hình cầu trong không gian Euclide. Y
whuber

1
@whuber, bình luận của bạn là những gì tôi đang chờ đợi; thực ra câu trả lời của tôi (về sự không đồng nhất, mà tôi liên kết đến) được dự định là một thách thức đối với bạn: có lẽ đó là một lời mời để gửi giải pháp của bạn - kỹ lưỡng và xuất sắc như bạn thường làm.
ttnphns

4

Tôi cảm thấy thích thực hiện một số chương trình, vì vậy tôi đã lấy câu trả lời đã bị xóa của @ Adam và quyết định viết một triển khai tốt đẹp trong R. Tôi tập trung vào việc sử dụng một phong cách định hướng theo chức năng (tức là lặp theo kiểu lapply). Ý tưởng chung là lấy hai vectơ, hoán vị ngẫu nhiên một trong các vectơ cho đến khi đạt được một mối tương quan nhất định giữa chúng. Cách tiếp cận này rất mạnh mẽ, nhưng đơn giản để thực hiện.

Đầu tiên chúng ta tạo một hàm cho phép ngẫu nhiên các vectơ đầu vào:

randomly_permute = function(vec) vec[sample.int(length(vec))]
randomly_permute(1:100)
  [1]  71  34   8  98   3  86  28  37   5  47  88  35  43 100  68  58  67  82
 [19]  13   9  61  10  94  29  81  63  14  48  76   6  78  91  74  69  18  12
 [37]   1  97  49  66  44  40  65  59  31  54  90  36  41  93  24  11  77  85
 [55]  32  79  84  15  89  45  53  22  17  16  92  55  83  42  96  72  21  95
 [73]  33  20  87  60  38   7   4  52  27   2  80  99  26  70  50  75  57  19
 [91]  73  62  23  25  64  51  30  46  56  39

... và tạo một số dữ liệu mẫu

vec1 = runif(100)
vec2 = runif(100)

... Viết một hàm cho phép vectơ đầu vào và tương quan nó với một vectơ tham chiếu:

permute_and_correlate = function(vec, reference_vec) {
    perm_vec = randomly_permute(vec)
    cor_value = cor(perm_vec, reference_vec)
    return(list(vec = perm_vec, cor = cor_value))
  }
permute_and_correlate(vec2, vec1)
$vec
  [1] 0.79072381 0.23440845 0.35554970 0.95114398 0.77785348 0.74418811
  [7] 0.47871491 0.55981826 0.08801319 0.35698405 0.52140366 0.73996913
 [13] 0.67369873 0.85240338 0.57461506 0.14830718 0.40796732 0.67532970
 [19] 0.71901990 0.52031017 0.41357545 0.91780357 0.82437619 0.89799621
 [25] 0.07077250 0.12056045 0.46456652 0.21050067 0.30868672 0.55623242
 [31] 0.84776853 0.57217746 0.08626022 0.71740151 0.87959539 0.82931652
 [37] 0.93903143 0.74439384 0.25931398 0.99006038 0.08939812 0.69356590
 [43] 0.29254936 0.02674156 0.77182339 0.30047034 0.91790830 0.45862163
 [49] 0.27077191 0.74445997 0.34622648 0.58727094 0.92285322 0.83244284
 [55] 0.61397396 0.40616274 0.32203732 0.84003379 0.81109473 0.50573325
 [61] 0.86719899 0.45393971 0.19701975 0.63877904 0.11796154 0.26986325
 [67] 0.01581969 0.52571331 0.27087693 0.33821824 0.52590383 0.11261002
 [73] 0.89840404 0.82685046 0.83349287 0.46724807 0.15345334 0.60854785
 [79] 0.78854984 0.95770015 0.89193212 0.18885955 0.34303707 0.87332019
 [85] 0.08890968 0.22376395 0.02641979 0.43377516 0.58667068 0.22736077
 [91] 0.75948043 0.49734797 0.25235660 0.40125309 0.72147500 0.92423638
 [97] 0.27980561 0.71627101 0.07729027 0.05244047

$cor
[1] 0.1037542

... và lặp đi lặp lại hàng ngàn lần:

n_iterations = lapply(1:1000, function(x) permute_and_correlate(vec2, vec1))

Lưu ý rằng các quy tắc phạm vi của R đảm bảo rằng vec1vec2được tìm thấy trong môi trường toàn cầu, bên ngoài hàm ẩn danh được sử dụng ở trên. Vì vậy, các hoán vị đều liên quan đến các bộ dữ liệu thử nghiệm ban đầu mà chúng tôi đã tạo.

Tiếp theo, chúng tôi tìm thấy mối tương quan tối đa:

cor_values = sapply(n_iterations, '[[', 'cor')
n_iterations[[which.max(cor_values)]]
$vec
  [1] 0.89799621 0.67532970 0.46456652 0.75948043 0.30868672 0.83244284
  [7] 0.86719899 0.55623242 0.63877904 0.73996913 0.71901990 0.85240338
 [13] 0.81109473 0.52571331 0.82931652 0.60854785 0.19701975 0.26986325
 [19] 0.58667068 0.52140366 0.40796732 0.22736077 0.74445997 0.40125309
 [25] 0.89193212 0.52031017 0.92285322 0.91790830 0.91780357 0.49734797
 [31] 0.07729027 0.11796154 0.69356590 0.95770015 0.74418811 0.43377516
 [37] 0.55981826 0.93903143 0.30047034 0.84776853 0.32203732 0.25235660
 [43] 0.79072381 0.58727094 0.99006038 0.01581969 0.41357545 0.52590383
 [49] 0.27980561 0.50573325 0.92423638 0.11261002 0.89840404 0.15345334
 [55] 0.61397396 0.27077191 0.12056045 0.45862163 0.18885955 0.77785348
 [61] 0.23440845 0.05244047 0.25931398 0.57217746 0.35554970 0.34622648
 [67] 0.21050067 0.08890968 0.84003379 0.95114398 0.83349287 0.82437619
 [73] 0.46724807 0.02641979 0.71740151 0.74439384 0.14830718 0.82685046
 [79] 0.33821824 0.71627101 0.77182339 0.72147500 0.08801319 0.08626022
 [85] 0.87332019 0.34303707 0.45393971 0.47871491 0.29254936 0.08939812
 [91] 0.35698405 0.67369873 0.27087693 0.78854984 0.87959539 0.22376395
 [97] 0.02674156 0.07077250 0.57461506 0.40616274

$cor
[1] 0.3166681

... Hoặc tìm giá trị gần nhất với tương quan 0,2:

n_iterations[[which.min(abs(cor_values - 0.2))]]
$vec
  [1] 0.02641979 0.49734797 0.32203732 0.95770015 0.82931652 0.52571331
  [7] 0.25931398 0.30047034 0.55981826 0.08801319 0.29254936 0.23440845
 [13] 0.12056045 0.89799621 0.57461506 0.99006038 0.27077191 0.08626022
 [19] 0.14830718 0.45393971 0.22376395 0.89840404 0.08890968 0.15345334
 [25] 0.87332019 0.92285322 0.50573325 0.40796732 0.91780357 0.57217746
 [31] 0.52590383 0.84003379 0.52031017 0.67532970 0.83244284 0.95114398
 [37] 0.81109473 0.35554970 0.92423638 0.83349287 0.34622648 0.18885955
 [43] 0.61397396 0.89193212 0.74445997 0.46724807 0.72147500 0.33821824
 [49] 0.71740151 0.75948043 0.52140366 0.69356590 0.41357545 0.21050067
 [55] 0.87959539 0.11796154 0.73996913 0.30868672 0.47871491 0.63877904
 [61] 0.22736077 0.40125309 0.02674156 0.26986325 0.43377516 0.07077250
 [67] 0.79072381 0.08939812 0.86719899 0.55623242 0.60854785 0.71627101
 [73] 0.40616274 0.35698405 0.67369873 0.82437619 0.27980561 0.77182339
 [79] 0.19701975 0.82685046 0.74418811 0.58667068 0.93903143 0.74439384
 [85] 0.46456652 0.85240338 0.34303707 0.45862163 0.91790830 0.84776853
 [91] 0.78854984 0.05244047 0.58727094 0.77785348 0.01581969 0.27087693
 [97] 0.07729027 0.71901990 0.25235660 0.11261002

$cor
[1] 0.2000199

Để có được mối tương quan cao hơn, bạn cần tăng số lần lặp.


2

Chúng ta hãy giải quyết một vấn đề tổng quát hơn: biến cách tạo các biến ngẫu nhiên với ma trận tương quan ?Y1Y2,,YnR

Giải pháp:

  1. nhận được sự phân tách mạnh mẽ của ma trận tương quanCCT=R
  2. tạo các vectơ ngẫu nhiên độc lập có cùng độ dài vớiY 1X2,,XnY1
  3. Sử dụng làm cột đầu tiên và nối các randoms được tạo vào nóY1
  4. Y i Y 1Y=CX , trong đó - các số tương quan ngẫu nhiên mới theo yêu cầu, lưu ý rằng sẽ không thay đổiYiY1

Mã Python:

import numpy as np
import math
from scipy.linalg import toeplitz, cholesky
from statsmodels.stats.moment_helpers import cov2corr

# create the large correlation matrix R
p = 4
h = 2/p
v = np.linspace(1,-1+h,p)
R = cov2corr(toeplitz(v))

# create the first variable
T = 1000;
y = np.random.randn(T)

# generate p-1 correlated randoms
X = np.random.randn(T,p)
X[:,0] = y
C = cholesky(R)
Y = np.matmul(X,C)

# check that Y didn't change
print(np.max(np.abs(Y[:,0]-y)))

# check the correlation matrix
print(R)
print(np.corrcoef(np.transpose(Y)))

Đầu ra thử nghiệm:

0.0
[[ 1.   0.5  0.  -0.5]
 [ 0.5  1.   0.5  0. ]
 [ 0.   0.5  1.   0.5]
 [-0.5  0.   0.5  1. ]]
[[ 1.          0.50261766  0.02553882 -0.46259665]
 [ 0.50261766  1.          0.51162821  0.05748082]
 [ 0.02553882  0.51162821  1.          0.51403266]
 [-0.46259665  0.05748082  0.51403266  1.        ]]

Bạn có thể làm rõ "không phải sẽ không thay đổi" nghĩa là gì không? Y1
whuber

@whuber đó là một lỗi đánh máy
Aksakal

0

Tạo các biến thông thường với ma trận hiệp phương sai SAMPLING như đã cho

covsam <- function(nobs,covm, seed=1237) {; 
          library (expm);
          # nons=number of observations, covm = given covariance matrix ; 
          nvar <- ncol(covm); 
          tot <- nvar*nobs;
          dat <- matrix(rnorm(tot), ncol=nvar); 
          covmat <- cov(dat); 
          a2 <- sqrtm(solve(covmat)); 
          m2 <- sqrtm(covm);
          dat2 <- dat %*% a2 %*% m2 ; 
          rc <- cov(dat2);};
          cm <- matrix(c(1,0.5,0.1,0.5,1,0.5,0.1,0.5,1),ncol=3);
          cm; 
          res <- covsam(10,cm)  ;
          res;

Tạo các biến bình thường với ma trận hiệp phương sai POPULATION như đã cho

covpop <- function(nobs,covm, seed=1237) {; 
          library (expm); 
          # nons=number of observations, covm = given covariance matrix;
          nvar <- ncol(covm); 
          tot <- nvar*nobs;  
          dat <- matrix(rnorm(tot), ncol=nvar); 
          m2 <- sqrtm(covm);
          dat2 <- dat %*% m2;  
          rc <- cov(dat2); }; 
          cm <- matrix(c(1,0.5,0.1,0.5,1,0.5,0.1,0.5,1),ncol=3);
          cm; 
          res <- covpop(10,cm); 
          res

2
Bạn cần học cách định dạng mã trong câu trả lời! Có một tùy chọn cụ thể để đánh dấu văn bản là các đoạn mã, sử dụng nó!
kjetil b halvorsen 6/2/2017

-6

Chỉ cần tạo một vectơ ngẫu nhiên và sắp xếp cho đến khi bạn nhận được r mong muốn.


Trong những tình huống này sẽ thích hợp hơn cho các giải pháp trên?
Andy W

Một tình huống mà người dùng muốn một câu trả lời đơn giản. Tôi đọc một câu hỏi tương tự trên diễn đàn r, và câu trả lời đã được đưa ra.
Adam

3
Thật không may, giải pháp này không chỉ không hiệu quả về mặt tính toán và gần đúng, nó thường sẽ thất bại hoàn toàn trừ khi một số phân tích được áp dụng lần đầu tiên để xác định phân phối thích hợp cho "vectơ ngẫu nhiên". Tôi nghĩ rằng có ý tưởng cơ bản là chỉ cần ném một số số ngẫu nhiên vào vấn đề và ngẫu nhiên cho phép chúng ( không "sắp xếp" chúng!) Cho đến khi đạt được một gần đúng (vì đây là cách nhanh chóng và dễ lập trình), nhưng ý tưởng đó không được thể hiện rõ ràng trong câu trả lời ngắn này. r
whuber

3
Nếu câu trả lời này được đưa ra trên diễn đàn trợ giúp, tôi nghi ngờ đó là (a) mỉa mai (nghĩa là như một trò đùa), hoặc (b) được cung cấp bởi một người không tinh vi về mặt thống kê. Nói một cách ngắn gọn hơn, đây là một câu trả lời kém cho câu hỏi. -1
gung - Tái lập 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.