2010-01-17 12 views
14

¿Existe alguna manera (distinta de un bucle for) de generar nuevas variables en un datagrama R, que serán todas las posibles interacciones bidireccionales entre las existentes? es decir, suponiendo una trama de datos con tres variables numéricas V1, V2, V3, me gustaría para generar las siguientes nuevas variables:Generación de variables de interacción en marcos de datos R

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

Ejemplo utilizando el bucle for:

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="") 

     } 
} 

Respuesta

27

Aquí es un chiste para ti, que también funciona si tiene factores:

> 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 No tenía conocimiento de la función model.matrix. ¡Muy útil! – Shane

+2

¡Excelente! También podría deshacerse de la intercepción irrelevante (en nuestro caso) model.matrix (~ (V1 + V2 + V3 + V4)^2-1, x) –

+2

que es. o para el caso completamente general como .data.frame (model.matrix (~.^2-1, x)) –

10

Aquí tienes, usando combn y apply:

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

Ajuste de los nombres de las columnas se puede hacer con dos paste comandos:

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

Por último, si desea que todas sus variables juntas, simplemente cbind ellos:

> 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

¡Muy bonito! ¿Hay alguna forma de cambiar también los nombres de las columnas, de acuerdo con el ejemplo, usando apply? –

+0

Lo actualicé para mostrar esto. – Shane

+1

Si solo vas a utilizar estas interacciones en modelos que toman fórmula, como lm o glm, no necesitas generar las variables. Ver: http://cran.r-project.org/doc/manuals/R-intro.html#Formulae-for-statistical-models – Tristan

0

Creo que esta pregunta debería complementarse con la función poly/polym, que va más allá: no solo genera interacciones entre las variables, sino también su poder hasta el grado seleccionado. Y orthogonal iteractions, que puede ser muy útil.

La solución directa al problema sería preguntado:

> 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 

Las columnas 4, 7, 8, 11, 12, 13 ha la solicitados en la pregunta. Otras columnas tienen otros tipos de interacciones. Si desea obtener interacciones ortogonales, simplemente configure raw = FALSE.

Cuestiones relacionadas