7

Trying to apply a matrix to a function, using mapply without success

I'm trying to solve a set of equations for different parameters. In a more simplistic form of the set of functions, I'm trying to pass a function to a matrix - constants -

     a b c
[1,] 1 4 7
[2,] 2 5 8
[3,] 3 6 9

and trying to solve the the equation 3*a + 2*b + 3*c and return the answer for each row in the matrix. I have changed the original function to a linear and more simple one - that is why I prefer using #mapply and that former explanations have not assisted me.

building the matrix

my_vector <- 1:9
constants <- matrix(my_vector, 3, 3)
colnames(constants) <- c("a", "b", "c")
constants

the target function

fun_abc <- function(a, b, c){
  return(3 * a + 2 * b + 3 * c)
}

applying constants to the function

mapply(fun_abc, 2, constants)

I keep getting Error in (function (a, b, c) : argument "c" is missing, with no default Can anyone spot the problems?

Amidavid
  • 177
  • 7
  • The function I've used is a simplified version of the function that I actually apply. It is not a linear function, therefore - I prefered using mapply. I edited the question as well. I commented on the post and edited the original question – Amidavid Sep 16 '19 at 10:36
  • Please clarify and/or reply to comments before posting a new question. – NelsonGon Sep 16 '19 at 13:51

3 Answers3

4

You can directly multiply values and take rowSums to get row-wise sum

vals <- c(3, 2, 3)
rowSums(t(t(constants) * vals))
#[1] 32 40 48

We use transpose since constants * vals would multiply vals in each column, so the first transpose is to multiply vals row-wise and the second transpose is to get matrix in original format again. If we would always have a square matrix (nrow == ncol), we can reduce one transpose and use colSums instead to get the same value.

colSums(t(constants) * vals)
#[1] 32 40 48

If we want to avoid transposing we can also use sweep

rowSums(sweep(constants, 2, vals, `*`))
Ronak Shah
  • 377,200
  • 20
  • 156
  • 213
2

One simple way to do this using matrix multiplication, and then changing it to vector if you want so:

my_vector <- 1:9
constants <- matrix(my_vector, 3, 3)
colnames(constants) <- c("a", "b", "c")
vals <- c(3, 2, 3)

c(constants %*% vals)
#> [1] 32 40 48

Or, redefine your function and use apply:

fun_x <- function(x){
  sum(x * vals) # same as 3 * x[1] + 2 * x[2] + 3 * x[3]
}

apply(constants, 1, fun_x)
akrun
  • 874,273
  • 37
  • 540
  • 662
yarnabrina
  • 1,561
  • 1
  • 10
  • 30
1

An alternative albeit admittedly overly complicated possibility:

   fun_abc <- function(my_matrix,multiplier,...){
 columns <- match(c(...),colnames(my_matrix))
 rowSums(mapply(function(x, y) my_matrix[,x] * y  , 
                columns, multiplier))

 }
 fun_abc(constants, c(3,2, 3),"a", "b", "c")
[1] 32 40 48

This assumes that the user would like to programmatically access columns, otherwise:

constants[,"a"] * 3 + constants[,"b"] * 2 + constants[,"c"] * 3
[1] 32 40 48
NelsonGon
  • 13,015
  • 7
  • 27
  • 57
  • The function I've used is a simplified version of the function that I actually apply. It is not a linear function, therefore - I prefered using mapply. I edited the question as well. – Amidavid Sep 16 '19 at 10:28
  • I cannot see a difference between your question and the original question. Could you actually include what the "non-linear" function should change to? – NelsonGon Sep 16 '19 at 12:41