2010-01-17 11 views
14

C'è un modo - diverso da un ciclo for - per generare nuove variabili in un frame di dati R, che saranno tutte le possibili interazioni a 2 vie tra quelle esistenti? cioè supponendo un dataframe con tre variabili numeriche V1, V2, V3, desidero generare i seguenti nuove variabili:Generazione di variabili di interazione in R dataframes

Inter.V1V2 (= V1 * V2) 
Inter.V1V3 (= V1 * V3) 
Inter.V2V3 (= V2 * V3) 

Esempio con ciclo:

x <- read.table(textConnection(' 
    V1 V2 V3 V4 
1 9 25 18 
2 5 20 10 
3 4 30 12 
4 4 34 16' 
), header=TRUE) 

dim.init <- dim(x)[2] 
for (i in 1: (dim.init - 1)) { 
     for (j in (i + 1) : (dim.init)) { 
       x[dim(x)[2] + 1] <- x[i] * x[j] 
       names(x)[dim(x)[2]] <- paste("Inter.V",i,"V",j,sep="") 

     } 
} 

risposta

27

Qui è un uno di linea per te, che funziona anche se si dispone di fattori:

> model.matrix(~(V1+V2+V3+V4)^2,x) 
    (Intercept) V1 V2 V3 V4 V1:V2 V1:V3 V1:V4 V2:V3 V2:V4 V3:V4 
1   1 1 9 25 18  9 25 18 225 162 450 
2   1 2 5 20 10 10 40 20 100 50 200 
3   1 3 4 30 12 12 90 36 120 48 360 
4   1 4 4 34 16 16 136 64 136 64 544 
attr(,"assign") 
[1] 0 1 2 3 4 5 6 7 8 9 10 
+0

+1 Non era a conoscenza della funzione model.matrix. Molto utile! – Shane

+2

Eccellente! Potresti anche eliminare l'irrilevante (nel nostro caso) intercettare model.matrix (~ (V1 + V2 + V3 + V4)^2-1, x) –

+2

proprio come sei. o per il caso generale as.data.frame (model.matrix (~.^2-1, x)) –

10

Qui si va, utilizzando combn e apply:

> x2 <- t(apply(x, 1, combn, 2, prod)) 

Impostazione dei nomi delle colonne può essere fatto con due paste comandi:

> colnames(x2) <- paste("Inter.V", combn(1:4, 2, paste, collapse="V"), sep="") 

Infine, se si desidera che insieme tutte le variabili, basta cbind loro:

> x <- cbind(x, x2) 
> V1 V2 V3 V4 Inter.V1V2 Inter.V1V3 Inter.V1V4 Inter.V2V3 Inter.V2V4 Inter.V3V4 
1 1 9 25 18   9   25   18  225  162  450 
2 2 5 20 10   10   40   20  100   50  200 
3 3 4 30 12   12   90   36  120   48  360 
4 4 4 34 16   16  136   64  136   64  544 
+0

Molto bello! C'è un modo per cambiare anche i nomi delle colonne, secondo l'esempio, usando apply? –

+0

L'ho aggiornato per mostrarlo. – Shane

+1

Se si stanno solo utilizzando queste interazioni in modelli che accettano la formula, come lm o glm, non è necessario generare le variabili. Vedi: http://cran.r-project.org/doc/manuals/R-intro.html#Formulae-for-statistical-models – Tristan

0

Penso che questa domanda dovrebbe essere integrata con la funzione , che va oltre: genera non solo le interazioni tra le variabili, ma la sua potenza fino al grado selezionato. E orthogonal iteractions, che può essere molto utile.

La direttamente soluzione al problema sarebbe chiesto:

> polym(x$V1, x$V2, x$V3, x$V4, degree = 2, raw = T) 
    1.0.0.0 2.0.0.0 0.1.0.0 1.1.0.0 0.2.0.0 0.0.1.0 1.0.1.0 0.1.1.0 0.0.2.0 0.0.0.1 1.0.0.1 0.1.0.1 0.0.1.1 0.0.0.2 
[1,]  1  1  9  9  81  25  25  225  625  18  18  162  450  324 
[2,]  2  4  5  10  25  20  40  100  400  10  20  50  200  100 
[3,]  3  9  4  12  16  30  90  120  900  12  36  48  360  144 
[4,]  4  16  4  16  16  34  136  136 1156  16  64  64  544  256 
attr(,"degree") 
[1] 1 2 1 2 2 1 2 2 2 1 2 2 2 2 

Le colonne 4, 7, 8, 11, 12, 13 è la richiesta nella domanda. Altre colonne hanno altri tipi di interazioni. Se desideri ottenere interazioni ortogonali, imposta semplicemente raw = FALSE.