2017-04-27 1 views
1
x1 x2 x3 x11 x12 x13 x22 x23 x33 
1 5 9 1 5 9 25 45 81 
2 6 10 4 12 20 36 60 100 
3 7 11 9 21 33 49 77 121 
4 8 12 16 32 48 64 96 144 

Lorsque x1, x2 et sont donnés, je voudrais créer un cadre de matrice ou des données x11, x12, x13, x22, x23 et x33 qui sont produit élément par élément de vecteurs x1, x2 et .Créer produit élément par élément de colonnes de la matrice

En fait, je voudrais à cela pour plus de vecteurs (par exemple x1 ~ x6) en ordre élevé (3ème ou 4ème). Y at-il une commande R qui peut faire cela?

+0

'm [, t (col (m)) [inférieur.tri (t (col (m)), diag = VRAI)]] * m [, rep (1: ncol (m), ncol (m) : 1)] '(je suis sûr que la première partie de la multiplication peut être simplifiée) – user2957945

+0

@ user2957945 Ceci est inspiré par ma réponse déjà postée. Même 'm [, rep (1: ncol (m), ncol (m): 1)]' est exactement le même. Si vous avez quelque chose de nouveau, alors allez-y! – 989

+0

@ 989; en fait ce n'était pas. C'était une tentative de le faire sans utiliser de boucle (c.-à-d. Générer la séquence c (1,2,3,2,3,3) mais plus généralement, il est possible de construire sur d'autres réponses si elles peuvent être améliorées - n'est pas une compétition. (Si j'étais intéressé par des points je le mettrais dans la section réponse) – user2957945

Répondre

2

Nous pouvons faire la combinaison avec expand.grid pour trouver toutes les combinaisons de colonnes 1: 3, puis une boucle à travers les lignes, sous-ensemble du jeu de données et obtenir le * de ceux

nm1 <- names(df1)[1:3] 
apply(expand.grid(nm1, nm1), 1, FUN = function(x) Reduce(`*`, df1[x])) 

La sortie ci-dessus donne toutes les combinaisons, mais supposons que si l'on veut éliminer les combinaisons qui sont l'image miroir

#expand the names to two columns with each combination 
d1 <- expand.grid(nm1, nm1) 
#remove the rows that are duplicates 
d2 <- d1[!duplicated(t(apply(d1, 1, sort))),] 
#apply the function and change the column names 
d3 <- apply(d2, 1, FUN = function(x) Reduce(`*`, df1[x])) 
colnames(d3) <- do.call(paste0, d2) 

et si nécessaire cbind avec les 3 premières colonnes

cbind(df1[1:3], d3) 

Une autre option est combn

d1 <- as.data.frame(combn(nm1, 2, FUN = function(x) Reduce(`*`, df1[x]))) 
nm2 <- combn(nm1, 2, FUN = paste, collapse="") 
names(d1) <- nm2 
d2 <- setNames(as.data.frame(df1[1:3]^2), paste0(nm1, nm1)) 
cbind(df1[1:3], d1, d2) 
0

Vous pouvez aussi le faire assez vectorisé dans la base R:

# Data 
m <- matrix(1:12,4,3) 

cl <- ncol(m) 
res <- cbind(m, m[,rep(seq(cl), cl:1)] * m[,unlist(Map(":", 1:cl, rep(cl,cl)))]) 

     # [,1] [,2] [,3] [,4] [,5] [,6] [,7] [,8] [,9] 
# [1,] 1 5 9 1 5 9 25 45 81 
# [2,] 2 6 10 4 12 20 36 60 100 
# [3,] 3 7 11 9 21 33 49 77 121 
# [4,] 4 8 12 16 32 48 64 96 144 

Fondamentalement, vous sélectionnez d'abord les colonnes pour lesquelles vous voulez avoir le produit et ensuite les faire tous en même temps.