David Lee David Lee - 1 month ago 21
R Question

Apply() for a function with two parameters to apply over

I have a function which have two parameters needed to be cycled. As far as I know,

apply()
only can apply over one array parameter with a dimension indicator. I wonder is there anyway to apply over two array parameters? Here is an example:

matrix_a <- matrix(1:6,3,2)
matrix_b <- matrix(2:7,3,2)


fun1 <- function(par1,par2){
mean(par1+par2) #true function are more complex than this
}

result <- numeric(nrow(matrix_a))

#this for loop give me exactly what I want, however, is there any sophistical way to do this? Like use a apply() function
for(i in 1:nrow(matrix_a)){
result[i] <- fun1(matrix_a[i,], matrix_b[i,])
}

Answer

If you're happy convert the matrices to transposed data frames, there are a number of nice options. So start with the following:

matrix_a <- matrix(1:6,3,2)
matrix_b <- matrix(2:7,3,2)

df_a <- data.frame(t(matrix_a))
df_b <- data.frame(t(matrix_b))

Note that use of t() to transpose is because your example involves rowwise operations. Your "more complex" function may not need this.

Then, some options are base mapply(), or few map* functions from the purrr package. Examples...

Using base mapply(), which accepts a function and multiple inputs to iterate over:

mapply(function(i, j) mean(i + j), df_a, df_b)
#> X1 X2 X3 
#>  6  8 10

Using purrr map2, which takes two inputs to iterate over:

library(purrr)
map2(df_a, df_b, ~ mean(.x + .y))      # returns list
#> $X1
#> [1] 6
#> 
#> $X2
#> [1] 8
#> 
#> $X3
#> [1] 10

map2_dbl(df_a, df_b, ~ mean(.x + .y))  # returns numeric vector
#> X1 X2 X3 
#>  6  8 10

Using purrr pmap() which takes a list of multiple inputs. Here I'll add a third data frame (b again) to demonstrate a more general example:

pmap_dbl(list(df_a, df_b, df_b), ~ mean(sum(.)))
#> X1 X2 X3 
#>  7  9 11
Comments