The situation is pretty straightforward. I want to create a matrix A of n rows and m columns, where the value for each element is given by a predetermined function f(i, j). What is the most elegant way to achieve this?
You can use outer:
outer(1:3,1:3,function(i,j) i^2+j)
[,1] [,2] [,3]
[1,] 2 3 4
[2,] 5 6 7
[3,] 10 11 12
It would help if you provided a reproducible example, but you could do something like this:
f <- function(i,j) i*j
m <- 4
n <- 2
out <- apply(expand.grid(1:m, 1:n), 1, function(x) f(x[1],x[2]))
dim(out) <- c(m,n)
Related
I would like to compute the product between the each row of a matrix x with itself. And then sum the result of all these products. The result is a scalar. I make the following coda that works but is not efficient. Can someone help me to avoid the for loop?
for(i in 1:nrow(x){
resid2[i] <- t(x[i,])%*% x[i,]
}
V = sum(resid2)/
The solution is just the sum of squares of all elements of the matrix.
V = sum(x^2)
which can also be calculated via matrix multiplication as:
V = crossprod(as.vector(x))
The intermediate vector resid2 can be calculated as
resid2 = rowSums(x^2)
V = sum(resid2)
Here is an answer that swaps the for loop out for the apply family.
sum(apply(x, margin = 1, function(z) z%*%z))
The apply function takes the matrix x, margin = 1 means for each row (as opposed to margin = 2 which means each column). So, for each row in x run a function that multiplies that row by itself: function(z) z%*%z
If I understand you correctly, you don't need to loop at all. mat %*% mat should do it:
mat <- matrix(seq.int(9), nrow=3)
mat
## [,1] [,2] [,3]
## [1,] 1 4 7
## [2,] 2 5 8
## [3,] 3 6 9
mat %*% mat
## [,1] [,2] [,3]
## [1,] 30 66 102
## [2,] 36 81 126
## [3,] 42 96 150
I have a simple matrix:
mat = rbind(c(1:3),c(4:6),c(7:9))
mat
# [,1] [,2] [,3]
# [1,] 1 2 3
# [2,] 4 5 6
# [3,] 7 8 9
I want to now reverse the matrix row-wise. That is I want to obtain:
revMat
# [,1] [,2] [,3]
# [1,] 3 2 1
# [2,] 6 5 4
# [3,] 9 8 7
To do this I tried
apply(mat, 1, rev)
And the result was:
# [,1] [,2] [,3]
# [1,] 3 6 9
# [2,] 2 5 8
# [3,] 1 4 7
I find this to be extremely strange. It's like the rows are reversed and then the final matrix is transposed. I don't understand why. If I try simply, for instance,
apply(mat, 2, rev)
it gives me the expected reversal of each column
# [,1] [,2] [,3]
# [1,] 7 8 9
# [2,] 4 5 6
# [3,] 1 2 3
Therefore to obtain the final result I have to perform
t(apply(t(bg), 2, rev))
Thus obtaining the required matrix is NOT a problem for me, but I don't understand the "anomaly" in the behavior of apply/ reverse. Can anyone explain this to me?
Edit: To make clear the distinction, I already know how to do the reversal. I want to know WHY this happens. How to is clear from many earlier questions including
How to reverse a matrix in R?
apply always puts the result in the first dimension. See ?apply for more information. Assuming this input:
mat <- matrix(1:9, 3, byrow = TRUE)
here are some alternatives:
1) transpose
t(apply(mat, 1, rev))
2) avoid apply with indexing
mat[, 3:1]
3) iapply An idempotent apply was posted here:
https://stat.ethz.ch/pipermail/r-help/2006-January/086064.html
Using that we have:
iapply(mat, 1, rev)
There was also an idempotent apply, iapply, in version 0.8.0 of the reshape package (but not in the latest version of reshape): https://cran.r-project.org/src/contrib/Archive/reshape/
4) rollapply rollapply in the zoo package can be used:
library(zoo)
rollapply(mat, 1, rev, by.column = FALSE)
5) tapply The tapply expression here returns a list giving us the opportunity to put it together in the way we want -- in this case using rbind:
do.call("rbind", tapply(mat, row(mat), rev))
6) multiply by a reverse diagonal matrix Since rev is a linear operator it can be represented by a matrix:
mat %*% apply(diag(3), 1, rev)
or
mat %*% (row(mat) + col(mat) == 3+1)
If you look at the help for apply(), this is exactly the behavior you would expect:
Value
If each call to FUN returns a vector of length n, then apply returns
an array of dimension c(n, dim(X)[MARGIN]) if n > 1.
a nice option to do what you want is to use indexing:
mat[,ncol(mat):1]
The main function is like the following code:
#f is a function that has two parameters and returns one value:
f <- function(a, b) {
a * b
}
#x is a's value group
x <- c(1,2,3,4)
#y is b's value group
y <- c(4,5,6)
I want to get all the possible values of f(x, y), and the result should be a matrix to be clear. Now I am using the for loop:
m <- c(NULL)
for (a in x) {
for (b in y) {
m <- c(m, c(a, b))
}
}
m <- matrix(m, 3, 4)
But it seems really very very silly.Can any one provide a simpler way?
Thank you.
outer(x, y, f)
# [,1] [,2] [,3]
#[1,] 4 5 6
#[2,] 8 10 12
#[3,] 12 15 18
#[4,] 16 20 24
outer(y, x, f)
# [,1] [,2] [,3] [,4]
#[1,] 4 8 12 16
#[2,] 5 10 15 20
#[3,] 6 12 18 24
I guess expand.grid is what you are looking for.
getAllCombinations <- function(a,b,r=3,col = 4){
# this is the key
g <- expand.grid(a,b)
matrix(g$Var1*g$Var2,r,col)
}
# call the function
getAllCombinations(x,y)
EDIT:
Gotta be a sportsman here. My own solution is actually the slowest by far, though it might be easier to understand than a lot of lapply and anonymous functions. If you'd benchmark it: #ExperimenteR does not only win the easy-to-read competition but also the race...
# performance
library(rbenchmark)
benchmark(
outer(x, y, f),
getAllCombinations(x,y),
vrajs(),
replications = 10000
)
Note that, I turned #vrajs solution into a function to keep things fair.
I hope following will work for you
#x is a's value group
x <- c(1,2,3,4)
#y is b's value group
y <- c(4,5,6)
matrix(unlist(lapply(1:length(x),
function(a){
lapply(1:length(y),
function(b){x[a]*y[b]})})),
ncol = length(y), byrow = TRUE)
[,1] [,2] [,3]
[1,] 4 5 6
[2,] 8 10 12
[3,] 12 15 18
[4,] 16 20 24
Update: Explanation of Code
Outer lapply function run through index of x and call inner lapply
for each element of x
Inner lapply function run through index of y and call function which will then return multiplication of index variable of x and y
unlist function unlist return list of lapply
matrix will create returned array according to dimension of y (as
number of columns)
The main function is like the following code:
#f is a function that has two parameters and returns one value:
f <- function(a, b) {
a * b
}
#x is a's value group
x <- c(1,2,3,4)
#y is b's value group
y <- c(4,5,6)
I want to get all the possible values of f(x, y), and the result should be a matrix to be clear. Now I am using the for loop:
m <- c(NULL)
for (a in x) {
for (b in y) {
m <- c(m, c(a, b))
}
}
m <- matrix(m, 3, 4)
But it seems really very very silly.Can any one provide a simpler way?
Thank you.
outer(x, y, f)
# [,1] [,2] [,3]
#[1,] 4 5 6
#[2,] 8 10 12
#[3,] 12 15 18
#[4,] 16 20 24
outer(y, x, f)
# [,1] [,2] [,3] [,4]
#[1,] 4 8 12 16
#[2,] 5 10 15 20
#[3,] 6 12 18 24
I guess expand.grid is what you are looking for.
getAllCombinations <- function(a,b,r=3,col = 4){
# this is the key
g <- expand.grid(a,b)
matrix(g$Var1*g$Var2,r,col)
}
# call the function
getAllCombinations(x,y)
EDIT:
Gotta be a sportsman here. My own solution is actually the slowest by far, though it might be easier to understand than a lot of lapply and anonymous functions. If you'd benchmark it: #ExperimenteR does not only win the easy-to-read competition but also the race...
# performance
library(rbenchmark)
benchmark(
outer(x, y, f),
getAllCombinations(x,y),
vrajs(),
replications = 10000
)
Note that, I turned #vrajs solution into a function to keep things fair.
I hope following will work for you
#x is a's value group
x <- c(1,2,3,4)
#y is b's value group
y <- c(4,5,6)
matrix(unlist(lapply(1:length(x),
function(a){
lapply(1:length(y),
function(b){x[a]*y[b]})})),
ncol = length(y), byrow = TRUE)
[,1] [,2] [,3]
[1,] 4 5 6
[2,] 8 10 12
[3,] 12 15 18
[4,] 16 20 24
Update: Explanation of Code
Outer lapply function run through index of x and call inner lapply
for each element of x
Inner lapply function run through index of y and call function which will then return multiplication of index variable of x and y
unlist function unlist return list of lapply
matrix will create returned array according to dimension of y (as
number of columns)
v1 <- c(1,2)
v2 <- c(3,4,5,6)
Is there a way to multiply these two vectors such that the result is a vector dim(1,3)
such as (11,14,17)
This is analogous to all possible dim(1,2) multiplication combinations such as
(1,2) %x% t(3,4), (1,2) %x% t(4,5), (1,2) %x% t(5,6)
It seems so simple, have looked and no luck.
Create a 2-row matrix:
> rbind(v2[-length(v2)],v2[-1])
[,1] [,2] [,3]
[1,] 3 4 5
[2,] 4 5 6
Then it's just matrix multi:
> v1 %*% rbind(v2[-length(v2)],v2[-1])
[,1] [,2] [,3]
[1,] 11 14 17
and subset if you want a vector:
> (v1 %*% rbind(v2[-length(v2)],v2[-1]))[1,]
[1] 11 14 17
Use subsetting and cbind to create a matrix of your combinations, then apply across the rows of this with your multiplication.
apply(cbind(v2[-length(v2)],v2[-1]),1,function(x) v1%*%x)
[1] 11 14 17
Similar to James' answer, but maybe simpler:
sapply(1:(length(v2)-1), function(j) sum(v1*v2[j:j+1]))
Since you're only multiplying vectors (aka 1-by-N matrices :-) ), there's no need to dive into the matrix ops.
Another option:
na.omit(filter(v2, rev(v1)))
You could also use embed:
apply(embed(v2, 2), 1, FUN='%*%', rev(v1))