lapply和do.call之间的区别是什么?

时间:2012-05-29 15:03:10

标签: r functional-programming

我最近在学习R并且被两个函数混淆:lapplydo.call。它们似乎与Lisp中的map函数类似。但为什么有两个具有不同名称的函数?为什么R只使用一个名为map的函数?

7 个答案:

答案 0 :(得分:110)

有一个名为Map的函数可能类似于其他语言的映射:

  • lapply返回与X长度相同的列表,其中每个元素都是将FUN应用于X的相应元素的结果。

  • do.call构造并执行来自名称或函数的函数调用以及要传递给它的参数列表。

  • Map将函数应用于给定向量的相应元素... Mapmapply的简单包装器,它不会尝试简化结果,类似于Common Lisp的mapcar(然而,参数被回收)。未来版本可能允许对结果类型进行一些控制。


  1. Mapmapply
  2. 的包装
  3. lapplymapply
  4. 的特例
  5. 因此Maplapply在许多情况下会相似。
  6. 例如,这里是lapply

    lapply(iris, class)
    $Sepal.Length
    [1] "numeric"
    
    $Sepal.Width
    [1] "numeric"
    
    $Petal.Length
    [1] "numeric"
    
    $Petal.Width
    [1] "numeric"
    
    $Species
    [1] "factor"
    

    同样使用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将函数作为输入,并将其其他参数展开给函数。例如,它被广泛用于将列表组合成更简单的结构(通常使用rbindcbind)。

    例如:

    x <- lapply(iris, class)
    do.call(c, x)
    Sepal.Length  Sepal.Width Petal.Length  Petal.Width      Species 
       "numeric"    "numeric"    "numeric"    "numeric"     "factor" 
    

答案 1 :(得分:57)

lapply在列表上应用函数,do.call调用带有参数列表的函数。这看起来对我很不一样......

举例说明:

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

通过lapply,您可以获得列表中每个元素的平均值:

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

[[2]]
[1] 5

[[3]]
[1] 8

do.call给出错误,因为平均值要求参数“trim”为1.

另一方面,rbind以行方式绑定所有参数。因此,要按行绑定X,请执行以下操作:

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

如果您使用lapply,则R会将rbind应用于列表的每个元素,为您提供这样的废话:

> 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

要想拥有像地图一样的东西,你需要?mapply,这是完全不同的东西。要获得例如X中每个元素的平均值,但使用不同的修剪,您可以使用:

> mapply(mean,X,trim=c(0,0.5,0.1))
[1] 2 5 8

答案 2 :(得分:29)

lapplymap类似,do.call则不是。 lapply将函数应用于列表的所有元素,do.call调用一个函数,其中所有函数参数都在列表中。因此,对于n元素列表,lapply具有n个函数调用,而do.call只有一个函数调用。因此do.calllapply完全不同。希望这能澄清你的问题。

代码示例:

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

lapply(c(1, 2, 4, 1, 2), function(x) x + 1)

答案 3 :(得分:24)

用最简单的话说:

  1. lapply() 为列表中的每个元素应用给定的函数,因此会有多个函数调用。

  2. do.call() 将一个给定的函数作为一个整体应用于列表,因此只有一个函数调用。

  3. 最好的学习方法是使用R文档中的函数示例。

答案 4 :(得分:12)

lapply()是类似地图的功能。 do.call()是不同的。它用于将参数传递给列表形式的函数,而不是枚举它们。例如,

> do.call("+",list(4,5))
[1] 9

答案 5 :(得分:10)

虽然有很多答案,但这是我的例子供参考。 假设我们有一个数据列表:

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

lapply函数返回一个列表。

lapply(L, sum) 

以上意思如下。

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

现在让我们为do.call做同样的事情

do.call(sum, L) 

这意味着

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

在我们的示例中,它返回21.简而言之,lapply总是返回一个列表,而do.call的返回类型实际上取决于执行的函数。

答案 6 :(得分:5)

两者之间的区别是:

lapply(1:n,function,parameters)

=&GT;这发送1,参数功能 =&GT;这发送2,参数功能 等等

do.call 

只需将1 ... n作为向量和参数发送到函数

所以在申请中你有n个函数调用,在do.call你只有一个

相关问题