Reputation: 2170
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
When x1
, x2
, and x3
are given, I would like to create a matrix or data frame x11, x12, x13, x22, x23
, and x33
which are element-wise product of vectors x1, x2
, and x3
.
Actually I would like to to this for more vectors (e.g. x1 ~ x6
) to high order (3rd or 4th).
Is there an R command which can do this?
Upvotes: 1
Views: 227
Reputation: 12937
You could also do this quite vectorized in 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
Basically you first select the columns for which you want to have the product and then do them all at once.
Upvotes: 0
Reputation: 887118
We can do the combination with expand.grid
to find all the combination of columns 1:3, then loop through the rows, subset the dataset and get the *
of those
nm1 <- names(df1)[1:3]
apply(expand.grid(nm1, nm1), 1, FUN = function(x) Reduce(`*`, df1[x]))
The above output gives all the combinations, but suppose if we want to remove the combinations that are mirror image
#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)
and if needed cbind
with the first 3 columns
cbind(df1[1:3], d3)
Another option is 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)
Upvotes: 2