기존 변수와 정의 된 상관 관계를 갖는 랜덤 변수 생성


71

시뮬레이션 연구를 위해 기존 변수 와의 미리 정의 된 (인구) 상관 관계를 나타내는 임의의 변수를 생성해야합니다 .Y

I는 들여다 R패키지 copulaCDVine소정 의존성 구조 랜덤 변수 분포를 생성 할 수있다. 그러나 결과 변수 중 하나를 기존 변수에 고정 할 수 없습니다.

기존 기능에 대한 아이디어와 링크를 부탁드립니다!


결론 : 서로 다른 솔루션으로 두 가지 유효한 답변이 나왔습니다.

  1. 사전 정의 된 변수 와 정확한 (샘플) 상관 관계를 갖는 랜덤 변수를 계산하는 caracal 별 R 스크립트
  2. R 기능 정의와 임의의 변수를 계산하는 나 자신을 발견, 인구 미리 정의 된 변수의 상관 관계를

[@ttnphns의 덧붙여서 : 나는 질문 제목을 단일 고정 변수 케이스에서 임의의 수의 고정 변수로 확장 할 자유를 얻었다; 즉, 고정 된 기존 변수와 미리 정의 된 상관을 갖는 변수를 생성하는 방법]


2
관련 질문 stats.stackexchange.com/questions/13382/… 를 참조하십시오 (질문의 이론적 측면).
매크로

다음 Q는 또한 밀접한 관련이 있으며 관심이있을 것입니다 : 상관 난수를 생성하는 방법 (제공된 분산 및 상관 정도) .
gung

답변:


56

여기 또 다른 하나가 있습니다. 평균이 0 인 벡터의 경우 상관은 해당 각도의 코사인과 같습니다. 따라서 각도 해당하는 원하는 상관 관계 가진 벡터 를 찾는 한 가지 방법은 다음 과 같습니다 .r θxrθ

  1. 고정 벡터 과 랜덤 벡터 얻습니다.x 2x1x2
  2. 두 벡터를 가운데에 놓고 (평균 0) 벡터를 제공합니다. , ˙ x 2x˙1x˙2
  3. 확인 직교 (직교 부분 공간 상에 투영)주는 ˙ x 1 ˙ x 2x˙2x˙1x˙2
  4. 스케일 와 길이 1주는 와 ˙ x 2 ˉ x 1 ˉ x 2x˙1x˙2x¯1x¯2
  5. ˉ x 1θ ˉ x 1rx1x¯2+(1/tan(θ))x¯1 은 각도가 인 벡터입니다. 는 이며 과의 상관 관계 는 입니다. 선형 변환에서는 상관 관계가 변경되지 않으므로 과의 상관 관계도 있습니다 .x¯1θx¯1rx1

코드는 다음과 같습니다.

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

여기에 이미지 설명을 입력하십시오

직교 투영법 , 분해를 사용하여 수치 안정성을 개선했습니다. 그 이후 단순히 이기 때문 입니다.Q R P = Q Q 'PQRP=QQ


SPSS 구문으로 코드를 다시 작성하려고했습니다. 20x1 열을 반환하는 QR 분해를 우연히 발견했습니다. SPSS에서 Gram-Schmidt orthonormalization (QR 분해도 있음)이 있지만 결과 Q 열을 복제 할 수 없습니다. QR 작업을 씹어 주시겠습니까? 또는 투영을 얻을 수있는 해결 방법을 표시하십시오. 감사.
ttnphns

@caracal P <- X %*% solve(t(X) %*% X) %*% t(X)은 r = 0.6을 생성하지 않으므로 해결 방법 이 아닙니다. 여전히 혼란 스러워요. ( Q <- qr.Q(qr(Xctr[ , 1, drop=FALSE]))SPSS에서 표현을 흉내
내게되어 기쁘지만

@ttnphns 혼란을 드려 죄송합니다. 제 의견은 일반적인 경우였습니다. 예제의 상황에 적용 : QR 분해를 통해 프로젝션 매트릭스를 얻는 것은 수치 안정성을위한 것입니다. 부분 공간이 행렬 의 열에 걸쳐있는 경우 투영 행렬을 로 얻을 수 있습니다 . R에서는 부분 공간이의 첫 번째 열에 걸쳐 있기 때문에 여기서 쓸 수 있습니다 . 직교 보체로의 투영을위한 매트릭스는 IP이다. XP=X(XX)1XXXctr[ , 1] %*% solve(t(Xctr[ , 1]) %*% Xctr[ , 1]) %*% t(Xctr[ , 1])Xctr
caracal

4
두 개 이상의 샘플에 대해 비슷한 것을 수행하는 방법을 누구든지 명확히 할 수 있습니까? rho와 짝을 이루는 3 개의 샘플을 원한다면 어떻게이 솔루션을 변환하여이를 달성 할 수 있습니까?
Andre Terra

한계 경우에 rho=1: 나는 이런 식으로 뭔가를 할 유용하다고 if (isTRUE(all.equal(rho, 1))) rho <- 1-10*.Machine$double.eps그렇지 않으면 내가 얻고 있었다, NaN
PatrickT

19

가장 일반적인 해결책을 설명하겠습니다. 이러한 일반적인 문제를 해결하면 두 줄의 짧은 R코드만으로도 매우 간단한 소프트웨어 구현을 달성 할 수 있습니다 .

벡터 선택 같은 길이, , 당신이 원하는 분포에 따라. 하자 의 최소 제곱 회귀의 잔차 수 에 대한 : 이것은 추출 에서 구성 요소를 . 다수의 적합한 다시 추가함으로써 로 , 우리는 임의의 상관 관계를 갖는 벡터 생성 할 수있다 와 . 임의의 추가 상수 및 양의 곱셈 상수까지-어떤 방식 으로든 자유롭게 선택할 수 있습니다.Y Y X Y Y X Y Y ρ YXYYXYYXYYρY

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

( " "는 표준 편차에 비례하는 계산을 나타냅니다.)SD


작동 R코드 는 다음과 같습니다 . 를 제공하지 않으면 코드는 다변량 표준 정규 분포에서 값을 가져옵니다.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)
}

예를 들어, 성분 으로 임의의 를 생성 하고이 와 다양한 지정된 상관 관계를 갖는 를 생성했습니다 . 그것들은 모두 같은 시작 벡터 졌습니다. 다음은 그들의 산점도입니다. 각 패널의 맨 아래에있는 "러품"은 일반적인 벡터를 보여줍니다 .50 X Y ; ρ Y X = ( 1 , 2 , , 50 ) YY50XY;ρYX=(1,2,,50)Y

그림

줄거리 사이에는 현저한 유사성이 있습니다.


실험하고 싶다면이 데이터와 그림을 생성 한 코드가 있습니다. (나는 결과를 이동하고 확장하기 위해 자유를 사용하지 않았으며 이는 쉬운 작업입니다.)

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 에서이 방법은 하나 이상의 쉽게 일반화됩니다 . 수학적으로 가능 하면 전체적으로 상관 관계가 지정된 를 세트 . 에서 모든 의 효과를 취하고 와 잔차 의 적절한 선형 조합을 형성 하려면 보통 최소 제곱을 사용 하십시오. ( 의사 역수를 계산하여 얻은 의 이중 기준으로이 작업을 수행하는 데 도움이됩니다 . follownig 코드는 의 SVD를 사용하여 이를 수행합니다.)X Y 1 , Y 2 , ... , Y의 K ; ρ 1 , ρ 2 , , ρ k Y i Y i X Y i Y YYXY1,Y2,,Yk;ρ1,ρ2,,ρkYiYiXYiYY

여기에서 알고리즘의 스케치의 R1, 행렬의 열로 주어진다는 :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)

다음은 실험을 원하는 사람들을위한보다 완벽한 구현입니다.

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))

이것은 실제로 좋은 해결책입니다. 그러나 여러 개의 변수 (답변의 고정 변수) 사례로 직접 확장하지 못했습니다 . 주장합니다. 보여줄 수 있습니까? R이 아닌 사용자가 주석이 달린 코드를 읽을 수 있습니까? YBTW, this method readily generalizes to more... Just use ordinary least squares... and form a suitable linear combination
ttnphns

1
@ttnphns 나는 그렇게했다.
whuber

1
정말 고마워! 나는 오늘 SPSS에 당신의 접근 방식을 코딩했다. 정말 좋은 제안입니다. 나는이 과제를 해결하기 위해 적용 가능한 이중 기초라는 개념을 결코 생각하지 않았다.
ttnphns

균일하게 분포 된 벡터를 생성하기 위해 비슷한 방법을 사용할 수 있습니까? 즉, 기존 벡터가 x있고 y상관 된 새로운 벡터를 생성하고 x싶지만 y벡터가 균일하게 분포 되기를 원합니다 .
Skumin

@Skumin 두 벡터 간의 관계를 제어 할 수 있도록 copula 사용을 고려하십시오.
whuber

6

또 다른 계산 방식이 있습니다 ( Enrico Schumann 의 포럼 게시물 에서 솔루션을 수정했습니다 ). 볼프강에 따르면 (이것은 주석 참조) ttnphns가 제안한 솔루션과 계산적으로 동일합니다.

caracal의 솔루션과 달리 의 정확한 상관 관계를 갖는 샘플을 생성하지 않고 모집단 상관 관계 가 동일한 두 벡터를 생성 합니다.ρρρ

다음 함수는 주어진 모집단에서 추출한 이변 량 샘플 분포를 계산할 수 있습니다 . 두 개의 임의 변수를 계산하거나 하나의 기존 변수 (parameter로 전달됨)를 가져와 원하는 상관 관계가있는 두 번째 변수를 만듭니다.ρ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)
}

이 함수는 parameter를 조정하여 비정규 한계 분포를 사용할 수도 있습니다 mar.fun. 그러나 하나의 변수를 수정 하는 것은 정규 분포 변수 에서만 작동하는 것 같습니다 x! (매크로의 주석과 관련이있을 수 있음).

또한 가우시안 분포와 피어슨 상관의 경우 결과 상관을 편향시키는 것처럼 보이기 때문에 원래 게시물 의 "작은 보정 계수" 가 제거되었습니다 (설명 참조).


이것은 대략적인 해결책 일뿐입니다. 즉 경험적 상관 관계는 정확히 와 같지 않습니다 . 아니면 뭔가 빠졌습니까? ρ
스라소니

1
"rho에 대한 작은 수정"(이 문맥에서 그 목적이 나를 피하는)을 제외하고는 ttnphns가 이전에 제안한 것과 정확히 동일하다는 것을 쉽게 알 수 있습니다. 이 방법은 단순히 원하는 변환 매트릭스를 얻기 위해 상관 행렬의 hole 레 스키 분해에 기초한다. 예를 들어 en.wikipedia.org/wiki/… 를 참조하십시오 . 그리고 네, 이것은 모집단 상관이 같은 두 개의 벡터 만 줄 것 rho입니다.
볼프강

"rho에 대한 작은 수정"은 원래 게시물에 있었고 여기 에 설명되어 있습니다 . 사실, 나는 그것을 정말로 이해하지 못한다. 그러나 rho = .3으로 50000 시뮬레이션 된 상관 관계를 조사한 결과 "작은 수정" 이 없으면 평균 r 's는 .299가 되고 , 수정을 사용하면 평균 .312 (보정 된 rho의 값)는 다음과 같습니다. 생산. 따라서 함수에서 해당 부분을 제거했습니다.
Felix S

나는 이것이 오래되었다는 것을 알고 있지만이 방법이 비양의 명확한 상관 행렬에는 작동하지 않는다는 점도 알고 싶습니다. 예를 들어 -1의 상관 관계입니다.
zzk

1
감사; 나는 눈치 그 1 개는 표준화되어 있지 않은 경우 평균 = 0, SD = 1, 그리고, 당신은 라인 수정해야합니다 당신은 오히려 크기를 조정하지 않는 게 좋을 : X2 <- mar.fun(n)X2 <- mar.fun(n,mean(x),sd(x))X1과 X2 사이의 원하는 상관 관계를 얻을
데이브 M

6

XYXrXrY=rX+EE0sd=1r2XYrXYXρ=r

rEXEXYX1,X2,X3,...

XrYYrY


2017 년 11 월 11 일 업데이트 . 오늘이 오래된 스레드를 발견했으며 처음에 말한 반복 피팅 알고리즘을 보여줌으로써 답변을 확장하기로 결정했습니다.

Y X

Disclamer : 나는 발견을 기반으로 우수한 하나의 열등 발견 한이 반복 솔루션 듀얼 기초제안 오늘이 스레드에서 @whuber에 의해. @ whuber의 솔루션은 반복적이지 않으며 더 중요하게는 "my"알고리즘보다 약간 적은 입력 "pig"변수의 값에 영향을 미치는 것으로 보입니다 (작업이 "수정"되면 자산이됩니다) 기존 변수이며 처음부터 임의의 변이를 생성하지 않습니다). 아직도, 나는 호기심과 그것이 효과가 있기 때문에 출판하고 있습니다 (각주 참조).

X1,X2,...,XmYYr1,r2,...,rmX

YXYY

  1. rdf=n1Sj=rjdfXjX

  2. 모든 변수를 Z- 표준화합니다 (각 중심, 그런 다음 이상에서 계산 된 표준 편차로 나눔 ). 와 는 표준입니다. 관찰 된 제곱합은 이제 = 입니다.Y X dfdfYXdf

  3. 목표 s : 에 따라 s로 를 예측하는 회귀 계수를 계산 합니다.YXrb=(XX)1S

  4. : 대해 예측 된 값을 계산하십시오 .YY^=Xb

  5. 잔차 계산 .E=YY^

  6. 잔차에 필요한 (목표) 제곱합을 계산합니다 : .SSS=dfSSY^

  7. (반복하기 시작합니다.) 현재 와 모든 사이의 합계 계산 :EXjCj=i=1nEiXij

  8. 모든 를 가깝게하기 위한 올바른 값 ( 는 사례 색인) :EC0i

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

    (분모는 반복에서 변경되지 않고 미리 계산합니다)

    또는 대안 적으로,보다 효율적인 공식은 의 평균 이 이되도록 보장합니다 . 먼저 7 단계에서 계산하기 전에 각 반복에서 를 중심으로 설정 한 다음이 8 단계에서 다음과 같이 수정하십시오.E0 EC

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

    (분모는 미리 알려져 있습니다)1

  9. 를 목표 값으로 가져 오십시오 .SSEEi[corrected]=EiSSS/SSE

    7. (DO, 말, 10-20 반복 단계로 이동, 더 큰이 . 목표 경우 더 많은 반복이 필요 할 수있는 의 현실이었다 긍정적이며, 표본 크기의 경우 너무 적은없는, 반복 항상 수렴에 직접 연결을 반복하십시오.)mrSSSn

  10. 준비 : 모든 가 거의 제로에 도달했습니다. 이는 잔차 가 목표 을 복원하도록 훈련되었음을 의미합니다 . 피팅 계산 : .CErYY[corrected]=Y^+E

  11. 얻어진 는 거의 표준화되어있다. 마지막 스트로크로, 2 단계에서 한 것처럼 다시 정확하게 표준화 할 수 있습니다.Y

  12. 당신은 제공 할 수 있습니다 어떤으로 분산 하고 의미 당신이 좋아. 실제로 네 가지 통계 중 min , max , mean , st가 있습니다. dev . -두 개의 값을 선택하고 변수를 선형으로 변환하여 달성 한 (상관)을 변경하지 않고 변수를 포즈화할 수 있습니다 (모두 선형 크기 조정이라고 함).Yr

위에서 말한 것을 다시 경고하기 위해. 를 정확하게 끌어 당기면 출력 는 정규 분포를 유지할 필요가 없습니다.YrY


1 보정 공식은 예를 들어 모든 에 대해 의 더 큰 동질성 (제곱합으로) 을 보장 하고 상관 관계를 얻는 동시에 더 정교해질 수 있습니다 .- 나는 그것을위한 코드를 구현했습니다. 너무. (whuber와 같은 더 깔끔하고 반복적이지 않은 접근 방식을 통해 이러한 "이중"작업을 해결할 수 있는지는 모르겠습니다 .)YX


1
답변 주셔서 감사합니다. 그것은 내가 생각했던 경험적 / 반복적 해결책입니다. 그러나 시뮬레이션을 위해서는 비용이 많이 드는 절차없이보다 분석적인 솔루션이 필요합니다. 다행스럽게도 방금 게시 할 솔루션을 찾았습니다.
Felix S

이것은 이변 량 법선을 생성하는 데 효과적이지만 임의 분포 (또는 비 첨가 분포)에는 작동하지 않습니다.
Macro

1
솔루션의 전체 원뿔을 직접 생성 할 수 있는데 왜 반복을 제안하는지 모르겠습니다. 이 접근법에 특별한 목적이 있습니까?
whuber

1
최신 편집 내용 다시 작성 : 모든 솔루션에 대해 간단한 공식을 제공하므로 모든 솔루션 세트에 대해 적절한 객관적인 기능을 최소화하여 "더 큰 동질성"과 같은 원하는 목표를 달성 할 수 있습니다. 이 접근법은 완전히 일반적입니다. 변수 (또는 변수들) 를 직교 기반으로 확장하고 상관의 스케일-불변량을 이용함으로써, 문제는 유클리드 공간에서 구체에 정의 된 함수를 최적화하는 것 중 하나가된다. Y
whuber

1
@ whuber, 당신의 의견은 내가 기다리고 있었던 것입니다; 실제로 내 대답 (내가 연결 된 이분산성에 관한)은 당신에게 도전으로 의도되었습니다. 아마도 평소와 같이 철저하고 훌륭하게 솔루션을 게시하라는 초대 일 것입니다.
ttnphns

4

나는 프로그래밍을하고 싶다고 생각했기 때문에 @Adam의 삭제 된 답변을 취하고 R로 멋진 구현을 작성하기로 결정했습니다. 나는 기능 지향 스타일 (즉, 랩 스타일 반복)을 사용하는 데 중점을 둡니다. 일반적인 아이디어는 두 벡터를 가져 와서 벡터 사이에 특정 상관 관계에 도달 할 때까지 벡터 중 하나를 무작위로 치환하는 것입니다. 이 접근 방식은 매우 무차별 적이지만 구현이 간단합니다.

먼저 입력 벡터를 무작위로 치환하는 함수를 만듭니다.

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

... 그리고 예제 데이터를 만드십시오

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

... 입력 벡터를 치환하고 참조 벡터와 상관시키는 함수를 작성하십시오.

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

... 그리고 수천 번 반복합니다.

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

R의 범위 지정 규칙을 확인합니다 vec1vec2위에서 사용 된 익명 함수 외부에서 글로벌 환경에서 발견된다. 따라서 순열은 모두 우리가 생성 한 원래 테스트 데이터 세트와 관련이 있습니다.

다음으로 최대 상관 관계를 찾습니다.

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

... 또는 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

더 높은 상관 관계를 얻으려면 반복 횟수를 늘려야합니다.


2

보다 일반적인 문제를 해결해 봅시다 : 변수 주어지면 상관 행렬 랜덤 변수 을 생성하는 방법은 무엇입니까?Y1Y2,,YnR

해결책:

  1. 상관 행렬 의 콜레 스키 분해를 구합니다.CCT=R
  2. 과 동일한 길이의 독립적 인 랜덤 벡터 을Y 1X2,,XnY1
  3. 을 첫 번째 열로 사용 하고 생성 된 난수를 추가하십시오Y1
  4. Y i Y 1Y=CX , - 필요에 따라 새로운 임의의 상관 관계 번호, 노트 것을 변경되지 않습니다YiY1

파이썬 코드 :

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)))

테스트 출력 :

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.        ]]

" 이 바뀌지 않을 것"이 무엇을 의미 하는지 명확히 할 수 있습니까? Y1
whuber

@whuber 오타했다
Aksakal

0

주어진 SAMPLING 공분산 행렬을 사용하여 정규 변수 생성

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;

주어진 POPULATION 공분산 행렬을 사용하여 정규 변수 생성

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
답변에서 코드를 포맷하는 법을 배워야합니다! 텍스트를 코드 조각으로 표시하는 특정 옵션이 있습니다!
kjetil b halvorsen

-6

임의의 벡터를 만들고 원하는 r을 얻을 때까지 정렬하십시오.


어떤 상황에서 위의 솔루션보다 선호됩니까?
Andy W

사용자가 간단한 답변을 원하는 상황. 나는 r 포럼에서 비슷한 질문과 그 답변을 읽었습니다.
Adam

3
r

3
이 답변이 r-help 포럼에 제공된 경우 (a) 아이러니 한 (즉, 농담으로 의도 된) 또는 (b) 통계적으로 정교하지 않은 사람이 제공 한 것으로 의심됩니다. 좀 더 간결하게 말하면, 이것은 질문에 대한 나쁜 대답입니다. -1
gung
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.