stu
stu

Reputation: 183

Using apply and multi argument functions

I want to apply a function over a data frame. The function takes V1 as arg1 and V2 as arg2 and I want to write the result to V3 or some other vector.

Is there an easy and compact way to do this? I've posted a (non-working) example below.

Thanks

Stu

my.func <- function(X, Y) {
  return(X + Y)
} 
a <- c(1,2,3)
b <- c(4,5,6)
my.df <- data.frame(a, b)
apply(my.df, 1, my.func, X="a", Y="b")

Upvotes: 2

Views: 96

Answers (4)

Simon O&#39;Hanlon
Simon O&#39;Hanlon

Reputation: 60000

There isn't really any need for an *apply function here. Vectorization would suffice:

my.df$c <- my.df$a + my.df$b
#  a b c
#1 1 4 5
#2 2 5 7
#3 3 6 9

Your apply solution can't work the way you have written it because apply does not pass a named vector through to your function: e.g.

colnames(my.df)
#[1] "a" "b"

apply( my.df , 1 , colnames )
#NULL

Upvotes: 1

Josh O&#39;Brien
Josh O&#39;Brien

Reputation: 162451

mapply() is made for this.

Either of the following will do the job. The advantage of the second approach is that it scales nicely to functions that take an arbitrary number of arguments.

mapply(my.func, my.df[,1], my.df[,2])
# [1] 5 7 9

do.call(mapply, c(FUN=list(my.func), unname(my.df)))
# [1] 5 7 9

Upvotes: 4

thelatemail
thelatemail

Reputation: 93938

I feel this would be better approached using with than mapply if you're calling elements inside a data.frame:

with(my.df,my.func(X=a,Y=b))
#[1] 5 7 9

It's still quite a clean method even if you need to do the explicit conversion from a matrix:

with(data.frame(my.mat),my.func(X=a,Y=b))
#[1] 5 7 9

Upvotes: 1

Alexander Hanysz
Alexander Hanysz

Reputation: 801

For your example, rowSums(my.df) will do the job. For more complicated tasks, you can use the mapply function. For example: mapply(my.func, my.df[a], my.df[b]).

Alternatively, you could rewrite your function to take a vector argument:

my.otherfunc <- function(x) sum(x)
apply(my.df, 1, my.otherfunc)

It's important to understand that when apply feeds each row or column into the function, it's sending one vector, not a list of separate entries. So you should give it a function with a single (vector) argument.

Upvotes: 0

Related Questions