[Em questões recentes, eu estava pensando em gerar vetores aleatórios em R e queria compartilhar essa "pesquisa" como uma sessão de perguntas e respostas independente em um ponto específico.]
A geração de dados aleatórios com correlação pode ser feita usando a decomposição de Cholesky da matriz de correlação aqui , como refletido em postagens anteriores aqui e aqui .
A questão que quero abordar é como usar a distribuição uniforme para gerar números aleatórios correlacionados de diferentes distribuições marginais em R .
r
correlation
sampling
random-variable
random-generation
Antoni Parellada
fonte
fonte
Respostas:
Desde que a pergunta é
e não apenas variáveis aleatórias normais, a resposta acima não produz simulações com a correlação pretendida para um par arbitrário de distribuições marginais em .R
O motivo é que, para a maioria das cdfs e , quando onde indica o cdf normal padrão.G Y cor ( X , Y ) ≠ cor ( G - 1 X ( Φ ( X ) , G - 1 Y ( Φ ( Y ) ) , ( X , Y ) ∼ N 2 ( 0 , Σ ) , ΦGX GY
A saber, aqui está um contra-exemplo com um Exp (1) e um Gamma (.2,1) como meu par de distribuições marginais em .R
Outro contra-exemplo óbvio é quando é o cdf de Cauchy, caso em que a correlação não é definida.GX
Para dar uma imagem mais ampla, aqui está um código R onde e são arbitrários:G YGX GY
Brincar com cdfs diferentes me levou a destacar esse caso especial de uma para e uma distribuição log-Normal para : G X G Yχ23 GX GY
que mostra a que distância da diagonal a correlação pode estar.
fonte
Eu escrevi o
correlate
pacote. As pessoas disseram que é promissor (digno de uma publicação no Journal of Statistical Software), mas eu nunca escrevi o artigo para ele porque escolhi não seguir uma carreira acadêmica.Acredito que o
correlate
pacote não mantido ainda esteja no CRAN.Ao instalá-lo, você pode fazer o seguinte:
O resultado é que os novos dados terão uma correlação de 0,5, sem alterar as distribuições univariadas de
a
eb
(os mesmos valores estão lá, eles apenas serão movidos até a correlação 0,5 multivariada ser atingida.Vou responder às perguntas aqui, desculpe pela falta de documentação.
fonte
Gere duas amostras de dados correlacionados a partir de uma distribuição aleatória normal padrão após uma correlação predeterminada .
Como exemplo, vamos escolher uma correlação r = 0,7 e codificar uma matriz de correlação, como:
(C <- matrix(c(1,0.7,0.7,1), nrow = 2)) [,1] [,2] [1,] 1.0 0.7 [2,] 0.7 1.0
Podemos usar
mvtnorm
para gerar agora essas duas amostras como um vetor aleatório bivariado:set.seed(0)
SN <- rmvnorm(mean = c(0,0), sig = C, n = 1e5)
resultando em dois componentes de vetor distribuídos como ~ e com a . Ambos os componentes podem ser extraídos da seguinte maneira:cor(SN[,1],SN[,2])= 0.6996197 ~ 0.7
X1 <- SN[,1]; X2 <- SN[,2]
Aqui está o gráfico com a linha de regressão sobreposta:
Use a Transformação Integral de Probabilidade aqui para obter um vetor aleatório bivariado com distribuições marginais ~ e a mesma correlação :U(0,1)
U <- pnorm(SN)
- então estamos alimentandopnorm
oSN
vetor para encontrar (ou ). No processo, preservamos o .Φ ( S N )cor(U[,1], U[,2]) = 0.6816123 ~ 0.7
Novamente, podemos decompor o vetor
U1 <- U[,1]; U2 <- U[,2]
e produzir um gráfico de dispersão com distribuições marginais nas bordas, mostrando claramente sua natureza uniforme:Aplique o método de amostragem por transformada inversa aqui para finalmente obter o bivetor de pontos igualmente correlacionados pertencentes a qualquer família de distribuição que nos propusemos a reproduzir.
A partir daqui, podemos gerar apenas dois vetores distribuídos normalmente e com variações iguais ou diferentes . Por exemplo:
Y1 <- qnorm(U1, mean = 8,sd = 10)
eY2 <- qnorm(U2, mean = -5, sd = 4)
, que manterá a correlação desejadacor(Y1,Y2) = 0.6996197 ~ 0.7
,.Ou opte por diferentes distribuições. Se as distribuições escolhidas são muito diferentes, a correlação pode não ser tão precisa. Por exemplo, vamost λ
U1
seguir uma distribuição com 3 df e um exponencial com a = 1: e The . Aqui estão os respectivos histogramas:λU2
Z1 <- qt(U1, df = 3)
Z2 <- qexp(U2, rate = 1)
cor(Z1,Z2) [1] 0.5941299 < 0.7
Aqui está um exemplo de código para todo o processo e os marginais normais:
Para comparação, reuni uma função baseada na decomposição de Cholesky:
Tentando ambos os métodos para gerar amostras correlacionadas (digamos, ) distribuídas ~ e que obtemos, definindo :N ( 97 , 23 ) N ( 32 , 8 )r=0.7 N(97,23) N(32,8)
set.seed(99)
Usando o uniforme:
e Usando o Cholesky:
fonte