2010-01-17 10 views
14

Existe-t-il un moyen - autre qu'une boucle for - de générer de nouvelles variables dans une trame R, qui seront toutes les interactions bidirectionnelles possibles entre les variables existantes? -à-dire en supposant une trame de données avec trois variables numériques V1, V2, V3, je voudrais générer les nouvelles variables suivantes:Génération de variables d'interaction dans les données R

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

Exemple avec boucle:

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

     } 
} 

Répondre

27

Voici une doublure pour vous qui fonctionne aussi si vous avez des facteurs:

> 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 N'a pas été informé de la fonction model.matrix. Très utile! – Shane

+2

Excellent! Vous pouvez également vous débarrasser du non pertinent (dans notre cas) intercepter model.matrix (~ (V1 + V2 + V3 + V4)^2-1, x) –

+2

droit vous êtes. ou pour le cas complètement général as.data.frame (model.matrix (~.^2-1, x)) –

10

Ici, vous allez, en utilisant combn et apply:

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

Définition des noms de colonnes peut être fait avec deux paste commandes:

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

Enfin, si vous voulez que toutes vos variables ensemble, juste cbind les:

> 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

Très bien! Existe-t-il un moyen de modifier également les noms de colonnes, selon l'exemple, en utilisant apply? –

+0

Je l'ai mis à jour pour le montrer. – Shane

+1

Si vous souhaitez simplement utiliser ces interactions dans des modèles prenant la formule, tels que lm ou glm, vous n'avez pas besoin de générer les variables. Voir: http://cran.r-project.org/doc/manuals/R-intro.html#Formulae-for-statistical-models – Tristan

0

Je pense que cette question devrait être complétée par la fonction poly/polym, qui va plus loin: elle génère non seulement des interactions entre les variables, mais aussi sa puissance jusqu'au degré sélectionné. Et orthogonal iteractions, ce qui peut être très utile.

La solution directement au problème posé serait:

> 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 

Les colonnes 4, 7, 8, 11, 12, 13 a demandé dans la question. Les autres colonnes ont d'autres types d'interactions. Si vous souhaitez obtenir des interactions orthogonales, définissez simplement raw = FALSE.

Questions connexes