lapply和do.call有什么区别?

Han*_*Sun 130 functional-programming r

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

And*_*rie 115

有一个叫做的函数Map可能类似于其他语言的map:

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

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

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


  1. Map 是一个包装 mapply
  2. lapply 是一个特例 mapply
  3. 因此Map,并lapply会在类似的情况.

例如,这里是lapply:

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

$Sepal.Width
[1] "numeric"

$Petal.Length
[1] "numeric"

$Petal.Width
[1] "numeric"

$Species
[1] "factor"
Run Code Online (Sandbox Code Playgroud)

同样使用Map:

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

$Sepal.Width
[1] "numeric"

$Petal.Length
[1] "numeric"

$Petal.Width
[1] "numeric"

$Species
[1] "factor"
Run Code Online (Sandbox Code Playgroud)

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" 
Run Code Online (Sandbox Code Playgroud)

  • 实际上我发现``do.call``几乎与Lisp中的``apply``相同 (4认同)

Jor*_*eys 58

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

举一个列表的例子:

X <- list(1:3,4:6,7:9)
Run Code Online (Sandbox Code Playgroud)

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

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

[[2]]
[1] 5

[[3]]
[1] 8
Run Code Online (Sandbox Code Playgroud)

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
Run Code Online (Sandbox Code Playgroud)

如果你愿意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
Run Code Online (Sandbox Code Playgroud)

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

> mapply(mean,X,trim=c(0,0.5,0.1))
[1] 2 5 8
Run Code Online (Sandbox Code Playgroud)


Pau*_*tra 31

lapply类似于map,do.call不是.lapply将函数应用于列表的所有元素,do.call调用一个函数,其中所有函数参数都在列表中.所以对于n元素列表,lapplyn函数调用,并且do.call只有一个函数调用.所以do.call与之完全不同lapply.希望这能澄清你的问题.

一个代码示例:

do.call(sum, list(c(1, 2, 4, 1, 2), na.rm = TRUE))
Run Code Online (Sandbox Code Playgroud)

和:

lapply(c(1, 2, 4, 1, 2), function(x) x + 1)
Run Code Online (Sandbox Code Playgroud)


Lov*_*eow 25

用最简单的话说:

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

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

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


fra*_*nkc 12

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

> do.call("+",list(4,5))
[1] 9
Run Code Online (Sandbox Code Playgroud)


kim*_*man 10

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

L=list(c(1,2,3), c(4,5,6))
Run Code Online (Sandbox Code Playgroud)

函数lapply返回一个列表.

lapply(L, sum) 
Run Code Online (Sandbox Code Playgroud)

以上意思如下.

list( sum( L[[1]]) , sum( L[[2]]))
Run Code Online (Sandbox Code Playgroud)

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

do.call(sum, L) 
Run Code Online (Sandbox Code Playgroud)

它的意思是

sum( L[[1]], L[[2]])
Run Code Online (Sandbox Code Playgroud)

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


小智 5

两者之间的区别是:

lapply(1:n,function,parameters)
Run Code Online (Sandbox Code Playgroud)

=>这个发送1,参数到函数=>这发送2,参数到功能等等

do.call 
Run Code Online (Sandbox Code Playgroud)

只需发送1 ... n作为矢量和参数即可运行

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