Für eine Simulationsstudie muss ich Zufallsvariablen generieren, die eine vorab festgelegte (Populations-) Korrelation zu einer vorhandenen Variablen .
Ich sah in die R
Pakete copula
und CDVine
der Zufall multivariate Verteilungen mit einer bestimmten Abhängigkeitsstruktur erzeugen kann. Es ist jedoch nicht möglich, eine der resultierenden Variablen an eine vorhandene Variable zu binden.
Anregungen und Links zu bestehenden Funktionen sind willkommen!
Schlussfolgerung: Es wurden zwei gültige Antworten mit unterschiedlichen Lösungen gefunden:
- Ein
R
Skript von caracal, das eine Zufallsvariable mit einer exakten (Beispiel-) Korrelation zu einer vordefinierten Variablen berechnet - Eine
R
Funktion, die ich selbst gefunden habe und die eine Zufallsvariable mit einer definierten Populationskorrelation zu einer vordefinierten Variablen berechnet
[@ttnphns 'Zusatz: Ich habe mir die Freiheit genommen, den Fragentitel von einem einzelnen Fall fester Variablen auf eine beliebige Anzahl fester Variablen zu erweitern; dh wie man eine Variable mit vordefinierten Korretationen mit einer oder mehreren festen, existierenden Variablen erzeugt]
quelle
Antworten:
Hier ist eine andere: Bei Vektoren mit dem Mittelwert 0 entspricht ihre Korrelation dem Kosinus ihres Winkels. Ein Weg, um einen Vektor mit genau der gewünschten Korrelation , die einem Winkel :r θX r θ
Hier ist der Code:
Für die orthogonale Projektion ich die Zerlegung verwendet, um die numerische Stabilität zu verbessern, da dann einfach .Q R P = Q Q 'P Q R P=QQ′
quelle
P <- X %*% solve(t(X) %*% X) %*% t(X)
erzeugt kein r = 0.6, das ist also nicht die Umgehung . Ich bin immer noch verwirrt. (Ich würde gerne Ihren AusdruckQ <- qr.Q(qr(Xctr[ , 1, drop=FALSE]))
in SPSS imitieren , weiß aber nicht wie.)Xctr[ , 1] %*% solve(t(Xctr[ , 1]) %*% Xctr[ , 1]) %*% t(Xctr[ , 1])
Xctr
rho=1
fand ich es nützlich, so etwas zu machen:if (isTRUE(all.equal(rho, 1))) rho <- 1-10*.Machine$double.eps
Ansonsten bekam ichNaN
sIch werde die allgemeinste mögliche Lösung beschreiben. Die Lösung des Problems in dieser Allgemeinheit ermöglicht es uns, eine bemerkenswert kompakte Softwareimplementierung zu erzielen: Nur zwei kurze
R
Codezeilen reichen aus.Wähle einen Vektor , der die gleiche Länge wie , nach einem der Verteilung Sie mögen. Lassen die Residuen der Regression der kleinsten Quadrate der seine gegen : Diese extrahiert die - Komponente von . Indem wir ein geeignetes Vielfaches von zu , können wir einen Vektor mit jeder gewünschten Korrelation mit erzeugen . Bis zu einer beliebigen additiven Konstante und positiven multiplikativen Konstante - die Sie nach Belieben wählen können - ist die LösungY Y ⊥ X Y Y X Y Y ⊥ & rgr; YX Y Y⊥ X Y Y X Y Y⊥ ρ Y
(" " steht für eine Berechnung, die proportional zu einer Standardabweichung ist.)SD
Hier istX
R
Arbeitscode. Wenn Sie kein angeben, der Code seine Werte aus der multivariaten Standardnormalverteilung.Zur Veranschaulichung habe ich ein zufälliges mit 50 Komponenten erzeugt und X Y erzeugt ; ρ mit verschiedenen spezifizierten Korrelationen mit diesem Y . Sie wurden alle mit demselben Startvektor X = ( 1 , 2 , … , 50 ) erstellt . Hier sind ihre Streudiagramme. Die "Rugplots" am unteren Rand jedes Panels zeigen den gemeinsamen Y- Vektor.Y 50 XY;ρ Y X=(1,2,…,50) Y
Es gibt eine bemerkenswerte Ähnlichkeit zwischen den Handlungen, nicht wahr :-).
Wenn Sie experimentieren möchten, finden Sie hier den Code, der diese Daten erzeugt hat, und die Abbildung. (Ich habe mich nicht darum gekümmert, die Freiheit zu nutzen, die Ergebnisse zu verschieben und zu skalieren. Das sind einfache Operationen.)
R
y
Das Folgende ist eine vollständigere Implementierung für diejenigen, die experimentieren möchten.
quelle
BTW, this method readily generalizes to more... Just use ordinary least squares... and form a suitable linear combination
x
und möchte einen neuen Vektor erzeugen, dery
mit diesem korreliert istx
, möchte aber auch, dass dery
Vektor gleichmäßig verteilt ist.Hier ist ein weiterer rechnerischer Ansatz (die Lösung stammt aus einem Forumsbeitrag von Enrico Schumann). Laut Wolfgang (siehe Kommentare) ist dies rechnerisch identisch mit der von ttnphns vorgeschlagenen Lösung.
x
Die Funktion kann auch nicht normale Randverteilungen verwenden, indem Parameter angepasst werden
mar.fun
. Beachten Sie jedoch, dass das Fixieren einer Variablen nur mit einer normalverteilten Variablen zu funktionieren scheintx
! (was sich auf Macros Kommentar beziehen könnte).Beachten Sie auch, dass der "kleine Korrekturfaktor" aus dem ursprünglichen Beitrag entfernt wurde, da er die resultierenden Korrelationen zu verzerren scheint, zumindest im Fall von Gaußschen Verteilungen und Pearson-Korrelationen (siehe auch Kommentare).
quelle
rho
.X2 <- mar.fun(n)
aufX2 <- mar.fun(n,mean(x),sd(x))
die gewünschte Korrelation zwischen x1 und x2 zu erhaltenUpdate 11. November 2017. Ich bin heute auf diesen alten Thread gestoßen und habe beschlossen, meine Antwort zu erweitern, indem ich den Algorithmus der iterativen Anpassung zeige, über die ich ursprünglich gesprochen habe.
Disclamer: Dieser iterative Lösung , die ich schlechter als die ausgezeichnete eine gefunden haben , basierend auf der Erkenntnis , duale Basis und vorgeschlagen von @whuber in diesem Thread heute. Die Lösung von @ whuber ist nicht iterativ und scheint, was für mich wichtiger ist, die Werte der Eingangsvariablen "pig" etwas weniger zu beeinflussen als "my" -Algorithmus (es wäre dann von Vorteil, wenn die Aufgabe darin besteht, "zu korrigieren". die vorhandene Variable und nicht von Grund auf zufällig zu generieren). Trotzdem veröffentliche ich meine aus Neugier und weil es funktioniert (siehe auch Fußnote).
(Der Nenner ändert sich bei Iterationen nicht. Berechnen Sie ihn im Voraus.)
quelle
Ich wollte etwas programmieren, also habe ich @ Adams gelöschte Antwort genommen und mich dazu entschlossen, eine nette Implementierung in R zu schreiben. Ich konzentriere mich auf die Verwendung eines funktional ausgerichteten Stils (dh Looping mit lappigem Stil). Die allgemeine Idee ist, zwei Vektoren zu nehmen, die zufällig einen der Vektoren permutieren, bis eine bestimmte Korrelation zwischen ihnen erreicht ist. Dieser Ansatz ist sehr brachial, aber einfach zu implementieren.
Zuerst erstellen wir eine Funktion, die den Eingabevektor zufällig permutiert:
... und einige Beispieldaten erstellen
... schreibe eine Funktion, die den Eingabevektor permutiert und ihn mit einem Referenzvektor korreliert:
... und tausendmal durchlaufen:
Beachten Sie, dass die Bereichsregeln von R sicherstellen, dass
vec1
undvec2
in der globalen Umgebung außerhalb der oben verwendeten anonymen Funktion gefunden werden. Die Permutationen sind also alle relativ zu den ursprünglichen Testdatensätzen, die wir generiert haben.Als nächstes finden wir die maximale Korrelation:
... oder finden Sie den nächsten Wert zu einer Korrelation von 0,2:
Um eine höhere Korrelation zu erhalten, müssen Sie die Anzahl der Iterationen erhöhen.
quelle
Lösung:
Python-Code:
Testausgang:
quelle
Generieren Sie normale Variablen mit der angegebenen SAMPLING-Kovarianzmatrix
Generieren Sie normale Variablen mit der angegebenen POPULATION-Kovarianzmatrix
quelle
Erstellen Sie einfach einen zufälligen Vektor und sortieren Sie, bis Sie das gewünschte r erhalten.
quelle