2013-09-03 8 views
7

Desidero creare una matrice di correlazione in base al vettore di correlazione, che è la matrice triangolare superiore (o inferiore) della matrice di correlazione.Creare una matrice di correlazione da un vettore di correlazione in R

L'obiettivo è trasformare questo vettore

enter image description here

a questa matrice di correlazione con 1s sulla diagonale.

enter image description here

Sai se c'è un metodo creando una matrice indicata triangolare sopra la diagonale e per impostare la diagonale di 1?

risposta

6

Non so se c'è un modo automatico per fare questo, ma ampliando il mio commento:

myvec <- c(-.55, -.48, .66, .47, -.38, -.46) 
mempty <- matrix(0, nrow = 4, ncol = 4) 
mindex <- matrix(1:16, nrow = 4, ncol = 4) 
mempty[mindex[upper.tri(mindex)]] <- myvec 
mempty[lower.tri(mempty)] <- t(mempty)[lower.tri(t(mempty))] 
diag(mempty) <- 1 
mempty 
#  [,1] [,2] [,3] [,4] 
# [1,] 1.00 -0.55 -0.48 0.47 
# [2,] -0.55 1.00 0.66 -0.38 
# [3,] -0.48 0.66 1.00 -0.46 
# [4,] 0.47 -0.38 -0.46 1.00 

Ecco una funzione rapidamente hacked insieme. Spero che tutti i miei passi di matematica siano corretti!

vec2symmat <- function(invec, diag = 1, byrow = TRUE) { 
    Nrow <- ceiling(sqrt(2*length(invec))) 

    if (!sqrt(length(invec)*2 + Nrow) %% 1 == 0) { 
    stop("invec is wrong length to create a square symmetrical matrix") 
    } 

    mempty <- matrix(0, nrow = Nrow, ncol = Nrow) 
    mindex <- matrix(sequence(Nrow^2), nrow = Nrow, ncol = Nrow, byrow = byrow) 
    if (isTRUE(byrow)) { 
    mempty[mindex[lower.tri(mindex)]] <- invec 
    mempty[lower.tri(mempty)] <- t(mempty)[lower.tri(t(mempty))] 
    } else { 
    mempty[mindex[upper.tri(mindex)]] <- invec 
    mempty[lower.tri(mempty)] <- t(mempty)[lower.tri(t(mempty))] 
    } 

    diag(mempty) <- diag 
    mempty 
} 

Qui è con un valore diverso per la diagonale.

vec2symmat(1:3, diag = NA) 
#  [,1] [,2] [,3] 
# [1,] NA 1 2 
# [2,] 1 NA 3 
# [3,] 2 3 NA 

Ecco un messaggio di errore se si tenta di fornire dati che non possono creare una matrice quadrata.

vec2symmat(1:4) 
# Error in vec2symmat(1:4) : 
# invec is wrong length to create a square symmetrical matrix 

E, con le impostazioni predefinite.

vec2symmat(1:10) 
#  [,1] [,2] [,3] [,4] [,5] 
# [1,] 1 1 2 3 4 
# [2,] 1 1 5 6 7 
# [3,] 2 5 1 8 9 
# [4,] 3 6 8 1 10 
# [5,] 4 7 9 10 1 
+0

una piccola ulteriore domanda: la funzione riempie la matrice per colonna, come posso riempire la matrice per righe, come illustrato nell'esempio precedente? Grazie mille !!! – jeffrey

+0

@jeffrey, ha aggiunto un argomento 'byrow' alla matrice. Controlla però la risposta di Greg Snow. – A5C1D2H2I1M1N2O1R2T1

+0

Funziona a meraviglia, proprio quello che sto cercando. Puoi spiegare i tuoi passi? Sono un noob con R e posso solo seguire fino ad ora. Grazie – AfterWorkGuinness

0

In qualsiasi linguaggio di programmazione penso che sarebbe solo farlo con un paio di cicli for innestati in questo modo:

Data:

vettore R; // Userò le parentesi tonde R (3) per indicare il terzo elemento basato su uno. // (che è memorizzato nella posizione di memoria R [2] nelle lingue con matrici basate su zero) int N;

Matrice M = Matrice (N, N); // una nuova istanza del tuo oggetto matrix, oppure puoi semplicemente usare gli array.

int i,j,k; 

k=1; 
for(i=1;i<N;i++) 
{ 
    M(i,i)=1; 
    for(j=i+1,j<=N;j++) 
    { 
     M(i,j)=M(j,i)=R[k]; 
     k=k+1; 
    } 
} 

Qui ho dato per scontato che tu sappia cosa sia N e che tu abbia oggetti di base come vettori e matrici disponibili. (In caso contrario, rappresentano un grande problema di esempio per la scrittura dei primi "oggetti") Strutture di dati complesse come vettori, matrici, numeri complessi e istogrammi rendono tutti gli oggetti ideali. Il modo giusto di pensare alla programmazione orientata agli oggetti per il lavoro scientifico è che tu usi gli oggetti per insegnare al tuo compilatore a capire i tipi di dati di alto livello che vuoi usare nel tuo vero lavoro ... Gli oggetti sono usati per creare un linguaggio di programmazione personalizzato ideale per il tuo tipo di lavoro. Tutto ciò che è genericamente utile dovrebbe andare nell'oggetto, dal momento che quegli oggetti cresceranno e si evolveranno per essere la vostra base di codice riutilizzabile.

Il codice di livello superiore può quindi essere un'applicazione molto potente, facile da leggere e pulita (poiché gran parte del lavoro di dettaglio viene eseguito negli oggetti) In alternativa, per la codifica rapida e sporca, il codice di livello superiore è dove hai messo tutti gli hack fragili. Dal momento che non è destinato a essere riutilizzabile.

Una volta ottenuto qualcosa di simile a questo debug, si dovrebbe semplicemente creare un costruttore di matrici che prende il vettore di correlazione e N come argomenti e inizializza la matricola per te.

Ovviamente se si utilizza un programma matematico grafico di alto livello che ha opinioni forti su ciò che è possibile fare con matrici e vettori, è necessario moltiplicare il vettore per N matrices per generare ciascuno di i vettori delle colonne della matricola finale. (Oppure leggere il manuale)

Per lo meno, si dovrà dirci ciò che il programma di matematica si chiama ... :)

+0

Guarda i tag domanda. La lingua è chiaramente indicata lì. – Roland

5

È possibile convincere R che il vettore è un oggetto a distanza poi utilizzare as.matrix per convertirlo:

> myvec <- c(-.55, -.48, .66, .47, -.38, -.46) 
> class(myvec) <- 'dist' 
> attr(myvec,'Size') <- 4 
> as.matrix(myvec) 
     1  2  3  4 
1 0.00 -0.55 -0.48 0.66 
2 -0.55 0.00 0.47 -0.38 
3 -0.48 0.47 0.00 -0.46 
4 0.66 -0.38 -0.46 0.00 

o una variazione sulla risposta da @AnandaMahto (simile alle parti interne utilizzati in precedenza):

> myvec <- c(-.55, -.48, .66, .47, -.38, -.46) 
> mycor <- matrix(0,4,4) 
> mycor[ col(mycor) < row(mycor) ] <- myvec 
> mycor <- mycor + t(mycor) 
> diag(mycor) <- 1 
> mycor 
     [,1] [,2] [,3] [,4] 
[1,] 1.00 -0.55 -0.48 0.66 
[2,] -0.55 1.00 0.47 -0.38 
[3,] -0.48 0.47 1.00 -0.46 
[4,] 0.66 -0.38 -0.46 1.00 
+0

+1 per l'inganno! :) – A5C1D2H2I1M1N2O1R2T1

+0

Devi aggiungere 'diag (1,4)' a 'as.matrix (myvec)'. –

3

una risposta con qualche aiuto funzioni che possono essere utili in altri problemi:

`lower.tri<-` <- function(x,value){ 
    x[lower.tri(x)] <- value 
    x 
} 

`upper.tri<-` <- function(x,value){ 
    y <- t(x) 
    lower.tri(y) <- value 
    t(y) 
} 

vec2mat <- function(r){ 
    n <- (1+sqrt(1+8*length(r)))/2 
    x <- diag(1,n) 
    lower.tri(x) <- upper.tri(x) <- r 
    x 
} 

EDIT: Si noti che upper.tri<- non è semplicemente ottenuto sostituendo "inferiore" su "superiore" in lower.tri<-. Ciò renderebbe il risultato asimmetrico.

risultati:

vec2mat(c(-0.55, -0.48, 0.66, 0.47, -0.38, -0.46)) 

     [,1] [,2] [,3] [,4] 
[1,] 1.00 -0.55 -0.48 0.66 
[2,] -0.55 1.00 0.47 -0.38 
[3,] -0.48 0.47 1.00 -0.46 
[4,] 0.66 -0.38 -0.46 1.00