using lapply for a function on a matrix with columns as elements in R

Viewed 517

I am still new to R, so please excuse if this is basic question. I have the following dataframe:

df <- data.frame(a=c(2,4,6,8), x = c(1,0,0,0), y=c(0,1,0,0), z=c(0,0,0,1))

> df
  a x y z
1 2 1 0 0
2 4 0 1 0
3 6 0 0 0
4 8 0 0 1

I define the function sumfunc as

sumfunc <- function(a,x,y,z){a*2+x+y-z}

So each row has the inputs a, x,y, z and I am expecting a vector of 4 elements.

  • element 1 = 5 (2*2+1+0-0)
  • element 2 = 9 (4*2+0+1-0)
  • element 3 = 12(6*2+0+0-0)
  • element 4 = 15 (8*2+0+0-1)

I tried using

abc <- lapply(df$a, FUN=sumfunc, x=df$x, y=df$y, z=df$z)

But this is not giving me the desired output. Kindly advice which apply family function is the right one for my use-case.
thanks very much!

6 Answers

Here are several ways. You do not need apply because R is vectorized:

with(df, a*2+x+y-z)
# [1]  5  9 12 15

with(df, sumfunc(a,x,y,z))
# [1]  5  9 12 15

If you really want to use apply):

apply(df, 1, function(x) sumfunc(x[1], x[2], x[3], x[4]))
# [1]  5  9 12 15

This is a good time to use mapply:

mapply(sumfunc, df$a, df$x, df$y, df$z)
# [1]  5  9 12 15

If you want to use this programmatically, and either the column names change or the number of arguments varies, then you can use it this way as well:

do.call(mapply, c(list(FUN=sumfunc), df))
# [1]  5  9 12 15

We could use pmap

library(purrr)
pmap_dbl(df, sumfunc)
[1]  5  9 12 15

Or may Vectorize the function and use do.call

do.call(Vectorize(sumfunc), df)
[1]  5  9 12 15

If you want do keep the data.frame here a simple solution

library(dplyr)

df %>% 
  mutate(sum = sumfunc(a,x,y,z))

  a x y z sum
1 2 1 0 0   5
2 4 0 1 0   9
3 6 0 0 0  12
4 8 0 0 1  15

And to return a single vector

df %>% 
  mutate(sum = sumfunc(a,x,y,z)) %>% 
  pull(sum)

[1]  5  9 12 15

Here is another easy solution:

library(purrr)

exec(sumfunc, !!!df)

[1]  5  9 12 15

I think I found and answer, though I am not sure if this is the most appropriate way

abc <- apply(X=as.data.frame(df$a), MARGIN=2, FUN=sumfunc, x=df$x,y=df$y, z=df$z)
Related