Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What's the difference between lapply and do.call?

I'm learning R recently and confused by two function: lapplyand do.call. It seems that they're just similar to map function in Lisp. But why are there two functions with such a different name? Why doesn't R just use a function called map?

like image 997
Hanfei Sun Avatar asked May 29 '12 15:05

Hanfei Sun


People also ask

Whats is do call?

call function. R has an interesting function called do. call. This function allows you to call any R function, but instead of writing out the arguments one by one, you can use a list to hold the arguments of the function.

What does Sapply do in R?

sapply() function in R Language takes list, vector or data frame as input and gives output in vector or matrix. It is useful for operations on list objects and returns a list object of same length of original set.

What is Mapply in R?

The mapply() function stands for 'multivariate' apply. Its purpose is to be able to vectorize arguments to a function that is not usually accepting vectors as arguments. In short, mapply() applies a Function to Multiple List or multiple Vector Arguments.

How do I use the reduce function in R?

Reduce() reduces a vector, x , to a single value by recursively calling a function, f , two arguments at a time. It combines the first two elements with f , then combines the result of that call with the third element, and so on. Calling Reduce(f, 1:3) is equivalent to f(f(1, 2), 3) .


7 Answers

There is a function called Map that may be similar to map in other languages:

  • lapply returns a list of the same length as X, each element of which is the result of applying FUN to the corresponding element of X.

  • do.call constructs and executes a function call from a name or a function and a list of arguments to be passed to it.

  • Map applies a function to the corresponding elements of given vectors... Map is a simple wrapper to mapply which does not attempt to simplify the result, similar to Common Lisp's mapcar (with arguments being recycled, however). Future versions may allow some control of the result type.


  1. Map is a wrapper around mapply
  2. lapply is a special case of mapply
  3. Therefore Map and lapply will be similar in many cases.

For example, here is lapply:

lapply(iris, class)
$Sepal.Length
[1] "numeric"

$Sepal.Width
[1] "numeric"

$Petal.Length
[1] "numeric"

$Petal.Width
[1] "numeric"

$Species
[1] "factor"

And the same using Map:

Map(class, iris)
$Sepal.Length
[1] "numeric"

$Sepal.Width
[1] "numeric"

$Petal.Length
[1] "numeric"

$Petal.Width
[1] "numeric"

$Species
[1] "factor"

do.call takes a function as input and splatters its other arguments to the function. It is widely used, for example, to assemble lists into simpler structures (often with rbind or cbind).

For example:

x <- lapply(iris, class)
do.call(c, x)
Sepal.Length  Sepal.Width Petal.Length  Petal.Width      Species 
   "numeric"    "numeric"    "numeric"    "numeric"     "factor" 
like image 73
Andrie Avatar answered Oct 14 '22 20:10

Andrie


lapply applies a function over a list, do.call calls a function with a list of arguments. That looks like quite a difference to me...

To give an example with a list :

X <- list(1:3,4:6,7:9)

With lapply you get the mean of every element in the list like this :

> lapply(X,mean)
[[1]]
[1] 2

[[2]]
[1] 5

[[3]]
[1] 8

do.call gives an error, as mean expects the argument "trim" to be 1.

On the other hand, rbind binds all arguments rowwise. So to bind X rowwise, you do :

> do.call(rbind,X)
     [,1] [,2] [,3]
[1,]    1    2    3
[2,]    4    5    6
[3,]    7    8    9

If you would use lapply, R would apply rbind to every element of the list, giving you this nonsense :

> lapply(X,rbind)
[[1]]
     [,1] [,2] [,3]
[1,]    1    2    3

[[2]]
     [,1] [,2] [,3]
[1,]    4    5    6

[[3]]
     [,1] [,2] [,3]
[1,]    7    8    9

To have something like Map, you need ?mapply, which is something different alltogether. TO get eg the mean of every element in X, but with a different trimming, you could use :

> mapply(mean,X,trim=c(0,0.5,0.1))
[1] 2 5 8
like image 42
Joris Meys Avatar answered Oct 14 '22 19:10

Joris Meys


lapply is similar to map, do.call is not. lapply applies a function to all elements of a list, do.call calls a function where all the function arguments are in a list. So for a n element list, lapply has n function calls, and do.call has just one function call. So do.call is quite different from lapply. Hope this clarifies your issue.

A code example:

do.call(sum, list(c(1, 2, 4, 1, 2), na.rm = TRUE))

and:

lapply(c(1, 2, 4, 1, 2), function(x) x + 1)
like image 23
Paul Hiemstra Avatar answered Oct 14 '22 20:10

Paul Hiemstra


In most simple words:

  1. lapply() applies a given function for each element in a list, so there will be several function calls.

  2. do.call() applies a given function to the list as a whole, so there is only one function call.

The best way to learn is to play around with the function examples in the R documentation.

like image 30
LoveMeow Avatar answered Oct 14 '22 19:10

LoveMeow


Although there have been many answers, here is my example for reference. Suppose we have a list of data as :

L=list(c(1,2,3), c(4,5,6))

The function lapply returns a list.

lapply(L, sum) 

The above means something like below.

list( sum( L[[1]]) , sum( L[[2]]))

Now let us do the same thing for do.call

do.call(sum, L) 

It means

sum( L[[1]], L[[2]])

In our example, it returns 21. In short, lapply always returns a list while the return type of do.call really depends on the function executed.

like image 41
kimman Avatar answered Oct 14 '22 20:10

kimman


lapply() is a map-like function. do.call() is different. It is used for passing the arguments to a function in list form instead of having them enumerated. For instance,

> do.call("+",list(4,5))
[1] 9
like image 43
frankc Avatar answered Oct 14 '22 20:10

frankc


The difference between both are :

lapply(1:n,function,parameters)

=> This send 1,parameters to function => this sends 2,parameters to function and so on

do.call 

Just sends 1…n as a vector and parameters to function

So in apply you have n function calls,in do.call you have just one

like image 29
nitin lal Avatar answered Oct 14 '22 19:10

nitin lal