はじめに

分析の実験をするときに、相関を持った2つの変数の乱数を発生させたいときがよくある。その関数をRで作った。ここで、ある相関を持った乱数を発生させるには以下の性質を用いる。すなわち、ある確率分布Aに従う乱数\(x\)に対して相関\(r\)を持つ乱数\(y\)は以下のように定義される。なお\(z\)は確率分布Aに従う乱数である。

\[ y = r \times x + \sqrt{(1 - r^2)} \times z \]

ただし、確率分布Aに従う完全な乱数を発生させるのは不可能である。そのことが原因で\(x\)\(y\)の相関係数は\(r\)と若干異なってしまう。そこで、何回も\(y\)を生成して最も\(r\)に近くなった時の\(y\)を用いることにした。

コード

以下は、そのコードである。

cor_get <- function(r, n, family = 'normal', rep = 1000, seed = 1234, 
                    mean = 0, sd = 1, lambda = 1, size = 10, prob = 0.5, 
                    min = 0, max = 1){
  
  set.seed(seed)
  
  if(family == 'normal'){
    x <- rnorm(n, mean, sd)
    y <- list() 
    cor <- NULL
    for(i in 1:rep){
      z <- rnorm(n, mean = mean, sd = sd)
      y[[i]] <- r * x + sqrt(1 - r^2)*z
      cor[i] <- cor(x, y[[i]])}
    }
  
  else if(family == 'binomial'){
    x <- rbinom(n, size, prob)
    y <- list() 
    cor <- NULL
    for(i in 1:rep){
      z <- rbinom(n, size, prob)
      y[[i]] <- r * x + sqrt(1 - r^2)*z
      cor[i] <- cor(x, y[[i]])}
    }
    
  else if(family == 'poisson'){
    x <- rpois(n, lambda)
    y <- list() 
    cor <- NULL
    for(i in 1:rep){
      z <- rpois(n, lambda)
      y[[i]] <- r * x + sqrt(1 - r^2)*z
      cor[i] <- cor(x, y[[i]])}
  }
  
  else if(family == 'uniform'){
    x <- runif(n, min, max)
    y <- list() 
    cor <- NULL
    for(i in 1:rep){
      z <- runif(n, min, max)
      y[[i]] <- r * x + sqrt(1 - r^2)*z
      cor[i] <- cor(x, y[[i]])}
  }
  
  else{warning('Warning: No such distribution', call. = F)}

  diff <- NULL
  for(i in 1:rep){
    diff[i] <- abs(cor[i] - r)
  }
  
  library(tidyverse)
  number <- 
    diff %>% 
    tibble() %>% 
    mutate(id = 1:rep) %>% 
    filter(. == min(diff)) %>% 
    select(id) %>% 
    as.numeric()
  
  df <- tibble(x, y[[number]])
  colnames(df) <- c("x", "y")
  
  return(list(df, cor(df[1], df[2])))
}

第1引数のrは目標の相関係数、第2引数のnはサンプル数、第3引数のfamilyは確率分布A、第4引数のrep\(y\)の生成回数(これを多くすれば精度がよくなる可能性が高まる)、第5引数のseedは乱数のseedである。それ以降の引数は、各確率分布に必要なパラメータである。ここでは、その確率分布として正規分布、二項分布、ポワソン分布、一様分布を設定することができる。 この関数はリスト形式でそのデータフレームと相関関係を出力する。なお、この関数を使うにはtidyverseをインストールしておく必要があることには留意されたい。