Code-Apprentice
Code-Apprentice

Reputation: 83537

Iterate over columns of a matrix in R

I have a function

function (x, y) { ... }

which expects two vectors x and y and returns a value calculated from them.

I want to apply this function pairwise to the column vectors of two matrices xs and ys. From R, iterating over the row vectors of a matrix I found mapply() but this seems to apply the function pairwise to each element of the matrix. Instead, I want to apply the function to an entire column. How do I do this?

For clarification, here's a contrived example:

xs <- matrix(c(1, 2, 3, 4, 5, 6), nrow = 3, ncol = 2)
ys <- matrix(c(25, 26, 27, 28, 29, 30), nrow = 3, ncol = 2)
dot <- function(x, y) sum(x*y)

Upvotes: 6

Views: 4315

Answers (5)

Karolis Koncevičius
Karolis Koncevičius

Reputation: 9656

Nobody yet mentioned asplit (added in R 3.6.0) - the function made specifically for this case.

Example:

mapply(dot, asplit(xs, 2), asplit(ys, 2))

Same but using rows:

mapply(dot, asplit(xs, 1), asplit(ys, 1))

Upvotes: 5

slava-kohut
slava-kohut

Reputation: 4233

You can also use mapply like this:

mapply(function(i, x = xs, y = ys) dot(x[,i],y[,i]), 1:ncol(xs))

or use purrr:

purrr::map_dbl(1:ncol(xs), function(i,x,y) dot(x[,i],y[,i]), x = xs, y = ys)

Upvotes: 1

akrun
akrun

Reputation: 887213

Using a simple for loop

v1 <- numeric(ncol(xs))
for(i in seq_along(v1)) v1[i] <- dot(xs[,i], ys[,i])
v1
#[1] 158 437

Or with vectorized option

colSums(xs * ys)
#[1] 158 437

Upvotes: 2

denis
denis

Reputation: 5673

mapply expect list or data frame to work on column:

mapply(dot,as.data.frame(xs),as.data.frame(ys))

 V1  V2 
158 437

Upvotes: 1

John Coleman
John Coleman

Reputation: 51998

Here is one way:

xs <- matrix(c(1, 2, 3, 4, 5, 6), nrow = 3, ncol = 2)
ys <- matrix(c(25, 26, 27, 28, 29, 30), nrow = 3, ncol = 2)
dot <- function(x, y) {
  sum(x*y)
}

dots <- sapply(1:ncol(xs),function(i) dot(xs[,i],ys[,i])) #dots = c(158, 437)

Upvotes: 2

Related Questions