Para um estudo de simulação, eu tenho que gerar variáveis aleatórias que mostram uma correlação pré-definida (população) com uma variável existente .
Examinei os R
pacotes copula
e CDVine
que podem produzir distribuições multivariadas aleatórias com uma determinada estrutura de dependência. No entanto, não é possível corrigir uma das variáveis resultantes em uma variável existente.
Todas as idéias e links para as funções existentes são apreciadas!
Conclusão: Surgiram duas respostas válidas, com diferentes soluções:
- Um
R
script de caracal, que calcula uma variável aleatória com uma correlação exata (de amostra) a uma variável predefinida - Uma
R
função que encontrei, que calcula uma variável aleatória com uma correlação populacional definida com uma variável predefinida
[Além do @ttnphns: tomei a liberdade de expandir o título da pergunta de uma única variável fixa para um número arbitrário de variáveis fixas; ou seja, como gerar uma variável com corretação (ões) predefinida (s) com algumas variáveis fixas existentes
fonte
Respostas:
Aqui está outro: para vetores com média 0, sua correlação é igual ao cosseno de seu ângulo. Então, uma maneira de encontrar um vetor com exatamente a correlação desejada r , correspondente a um ângulo θ :x r θ
Aqui está o código:
Para a projecção ortogonal , I utilizado o Q R -decomposition para melhorar a estabilidade numérico, uma vez que, em seguida, simplesmente P = Q Q ' .P Q R P= Q Q′
fonte
P <- X %*% solve(t(X) %*% X) %*% t(X)
não produz r = 0,6, então essa não é a solução alternativa . Ainda estou confuso. (Eu ficaria feliz para imitar a expressãoQ <- qr.Q(qr(Xctr[ , 1, drop=FALSE]))
em SPSS, mas não sei como.)Xctr[ , 1] %*% solve(t(Xctr[ , 1]) %*% Xctr[ , 1]) %*% t(Xctr[ , 1])
Xctr
rho=1
Achei que seria útil para fazer algo como isto:if (isTRUE(all.equal(rho, 1))) rho <- 1-10*.Machine$double.eps
, caso contrário, eu estava ficandoNaN
sVou descrever a solução mais geral possível. Resolver o problema nessa generalidade nos permite obter uma implementação de software notavelmente compacta: apenas duas pequenas linhas de
R
código são suficientes.Escolha um vetor , do mesmo comprimento que Y , de acordo com a distribuição que desejar. Vamos Y ⊥ ser os resíduos da regressão de mínimos quadrados de X contra Y : esta extrai a Y componente de X . Por via da adição de um múltiplo apropriado de Y para Y ⊥ , que pode produzir um vector com qualquer correlação desejada ρ com Y . Até uma constante aditiva arbitrária e uma constante multiplicativa positiva - que você pode escolher de qualquer forma - a solução éX Y Y⊥ X Y Y X Y Y⊥ ρ Y
(" " significa qualquer cálculo proporcional a um desvio padrão.)SD
Aqui está oX
R
código de trabalho . Se você não fornecer , o código extrairá seus valores da distribuição normal padrão multivariada.Para ilustrar, gerei um aleatório com 50 componentes e produzi X Y ; ρ tendo várias correlações indicados com esta Y . Todos foram criados com o mesmo vetor inicial X = ( 1 , 2 , … , 50 ) . Aqui estão os gráficos de dispersão. Os "rugplots" na parte inferior de cada painel mostram o vetor Y comum .Y 50. XY; ρ Y X= ( 1 , 2 , … , 50 ) Y
Há uma notável semelhança entre as parcelas, não é :-).
Se você deseja experimentar, aqui está o código que produziu esses dados e a figura. (Não me preocupei em usar a liberdade para alterar e escalar os resultados, que são operações fáceis.)
Aliás, esse método generaliza prontamente para mais de um : se for matematicamente possível, ele encontrará um X Y 1 , Y 2 , ... , Y k ; ρ 1 , ρ 2 , … , ρ k tendo correlações especificadas com um conjunto inteiro de Y i . Apenas use mínimos quadrados comuns para eliminar os efeitos de todo o Y i de X e formar uma combinação linear adequada do Y iY XY1 1, Y2, ... , Yk; ρ1 1, ρ2, … , Ρk YEu YEu X YEu e os resíduos. (Ajuda a fazer isso em termos de uma base dupla para , que é obtida computando uma pseudo-inversa. O código a seguir usa o SVD de Y para fazer isso.)Y Y
Aqui está um esboço do algoritmo emYEu
R
, onde o são dadas como colunas de uma matriz :y
A seguir, é apresentada uma implementação mais completa para aqueles que desejam experimentar.
fonte
BTW, this method readily generalizes to more... Just use ordinary least squares... and form a suitable linear combination
x
e quero gerar um novo vetory
correlacionado,x
mas também quero que oy
vetor seja distribuído uniformemente.Aqui está outra abordagem computacional (a solução é adaptada de uma postagem no fórum de Enrico Schumann). Segundo Wolfgang (ver comentários), isso é computacionalmente idêntico à solução proposta por ttnphns.
Em contraste com a solução de caracal, não produz uma amostra com a correlação exata de , mas dois vetores cuja correlação populacional é igual a ρ .ρ ρ
A função a seguir pode calcular uma distribuição de amostra bivariada obtida de uma população com um dado . Ele calcula duas variáveis aleatórias ou pega uma variável existente (passada como parâmetro ) e cria uma segunda variável com a correlação desejada:ρ
x
A função também pode usar distribuições marginais não normais ajustando o parâmetro
mar.fun
. Note, no entanto, que a fixação de uma variável única parece funcionar com uma variável normalmente distribuídax
! (que pode estar relacionado ao comentário da macro).Observe também que o "pequeno fator de correção" do post original foi removido, pois parece influenciar as correlações resultantes, pelo menos no caso de distribuições gaussianas e correlações de Pearson (também ver comentários).
fonte
rho
.X2 <- mar.fun(n)
paraX2 <- mar.fun(n,mean(x),sd(x))
obter a correlação desejada entre x1 e x2Seja sua variável fixa e você deseja gerar a variável Y que se correlaciona com X pela quantidade r . Se X é padronizado, então (porque r é coeficiente beta em regressão simples) Y = r X + E , onde E é variável aleatória da distribuição normal com média 0 e sd = √X Y X r X r Y= r X+ E E 0 0 . A correlação observada entre osdadosXeYserá aproximadamenter; XeYpodem ser vistos como amostras aleatórias dapopulaçãonormal bivariada(seXé normal) comρ=r.sd = 1 - r2-----√ X Y r X Y X ρ = r
Agora, se você deseja obter a correlação na sua amostra bivariada exatamente , é preciso prever que E tem de zero correlação com X . Esse aperto em zero pode ser alcançado com a modificação E iterativamente. Bem, com apenas duas variáveis, uma dada ( X ) e um para gerar ( Y ), o número suficiente de iterações é, na verdade, um, mas com múltiplas variáveis de dados ( X 1 , X 2 , X 3 , . . . ) Iterações ser necessário.r E X E X Y X1 1, X2, X3, . . .
Deve-se notar que, se é normal, no primeiro procedimento (" r aproximado ") Y também será normal; no entanto, no ajuste iterativo de Y para o " r exato " Y provavelmente perderá a normalidade porque o ajuste explora os valores de caso seletivamente.X r Y Y r Y
Atualize 11 de novembro de 2017. Encontrei esse tópico antigo hoje e decidi expandir minha resposta, mostrando o algoritmo do ajuste iterativo sobre o qual eu estava falando inicialmente.
Aqui está uma solução iterativa de como treinar uma variável simulada ou preexistente aleatoriamente para correlacionar ou covaria exatamente como desejamos (ou muito próximo disso - dependendo do número de iterações) com um conjunto de variáveis X s (elas não podem ser modificadas).Y X
Disclamer: Esta solução iterativa que eu achei inferior à excelente, com base em encontrar a base dupla e proposta por @whuber neste tópico hoje. A solução @ whuber não é iterativa e, mais importante para mim, parece estar afetando os valores da variável "pig" de entrada um pouco menos do que o algoritmo "my" (seria um recurso, se a tarefa fosse "corrigir" variável existente e não gerar variável aleatória a partir do zero). Ainda assim, estou publicando o meu por curiosidade e porque funciona (veja também Nota de rodapé).
Então, temos dado (fixos) variáveis , e varible Y que é ou apenas gerado aleatoriamente "porco" de valores ou é uma variável de dados existente quais os valores que precisam de "correcta" - para trazer Y exactamente a correlações (ou pode ser covariâncias) r 1 , r 2 , . . . , r m com os X s. Todos os dados devem ser contínuos; em outras palavras, deve haver uma grande quantidade de valores únicos.X1 1, X2, . . . , Xm Y Y r1 1, r2, . . . , rm X
A ideia: realizar ajuste iterativo de resíduos. Conhecendo as correlações / covariâncias desejadas (alvo), podemos calcular os valores previstos para o usando os Xs como múltiplos preditores lineares. Depois de obter os resíduos iniciais (do Y atual e da previsão ideal), treine-os iterativamente para não se correlacionar com os preditores. No final, recupere Y com os resíduos. (O procedimento foi minha própria invenção experimental da roda, muitos anos atrás, quando eu não conhecia a teoria; eu a codifiquei no SPSS.)Y X Y Y
Converta o destino s em somas de produtos cruzados multiplicando-os por df = n - 1 : S j = r j df . ( j é um índice de variável X ).r df = n - 1 Sj= rjdf j X
Padronize Z todas as variáveis (centralize cada uma delas e divida pelo desvio padrão calculado sobre aquela acima ). Y e X s são, portanto, padrão. As somas de quadrados observadas são agora = df .df Y X df
Calcular os coeficientes de predição regressivo por X s de acordo com o alvo r s: b = ( X ' x ) - 1 S .Y X r b = ( X′X )- 1S
Calcular os valores previstos para : Y = X b .Y Y^= X b
Calcular resíduos .E=Y- Y^
Calcular a soma necessária (alvo) de quadrados para resíduos: .SSS= df - SSY^
(o denominador não muda nas iterações, calcule-o com antecedência)
fonte
Eu estava com vontade de fazer alguma programação, então peguei a resposta excluída de @ Adam e decidi escrever uma boa implementação em R. Eu me concentro em usar um estilo orientado a funções (por exemplo, looping no estilo lapply). A idéia geral é pegar dois vetores, permutar aleatoriamente um dos vetores até que uma certa correlação seja alcançada entre eles. Essa abordagem é muito bruta, mas é simples de implementar.
Primeiro, criamos uma função que permite aleatoriamente o vetor de entrada:
... e crie alguns dados de exemplo
... escreva uma função que permita o vetor de entrada e a correlacione com um vetor de referência:
... e itere mil vezes:
Observe que as regras de escopo de R garantem isso
vec1
evec2
são encontradas no ambiente global, fora da função anônima usada acima. Portanto, todas as permutações são relativas aos conjuntos de dados de teste originais que geramos.Em seguida, encontramos a correlação máxima:
... ou encontre o valor mais próximo de uma correlação de 0,2:
Para obter uma correlação mais alta, você precisa aumentar o número de iterações.
fonte
Solução:
Código Python:
Saída de teste:
fonte
Gere variáveis normais com a matriz de covariância SAMPLING, conforme indicado
Gere variáveis normais com a matriz de covariância POPULATION, conforme indicado
fonte
Basta criar um vetor aleatório e classificar até obter o r desejado.
fonte