lapplyとdo.callの違いは何ですか?


143

私は最近Rを学んでいて、2つの関数で混乱しています:lapplydo.callmapLispの機能とちょうど同じようです。しかし、なぜこのような異なる名前の2つの関数があるのでしょうか。なぜRは呼び出された関数を使用しないのmapですか?

回答:


125

Map他の言語のmapと同様の関数が呼び出されます:

  • lapply Xと同じ長さのリストを返します。各要素は、Xの対応する要素にFUNを適用した結果です。

  • do.call 名前または関数とそれに渡される引数のリストから関数呼び出しを作成して実行します。

  • Map与えられたベクトルの対応する要素に関数を適用します... Common Lispのmapcar(ただし、引数はリサイクルされます)と同様に、結果を単純化しようとしないMap単純なラッパーmapplyです。将来のバージョンでは、結果タイプをある程度制御できるようになる可能性があります。


  1. Map ラッパーです mapply
  2. lapply の特別なケースです mapply
  3. したがってMaplapply多くの場合に似ています。

たとえば、ここにあり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関数を入力として受け取り、関数への他の引数を飛び散らせます。たとえば、リストをより単純な構造に(多くの場合、rbindまたはcbind)。

例えば:

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

4
実際に私が見つけたのdo.callapply、Lisp とほとんど同じです
Hanfei Sun

do.call(cbind, x)現在のバージョンであるはずの最後の例が私に与えるものではありませんError in do.call(c, x) : 'what' must be a function or character string...
sindri_baldur

1
@snoramその例はまだ機能します。関数cbind()は関数とは異なりc()、これでも機能しますが、結果は異なります。
Andrie

61

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 平均は引数「トリム」が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

Mapのようなものを作成するには、が必要?mapplyです。たとえばXのすべての要素の平均を取得するには、次のように使用できます。

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

34

lapply似ているmapdo.callではありません。lapplyリストのすべての要素に関数を適用し、do.callすべての関数引数がリストにある関数を呼び出します。そこらのn要素リスト、lapply持っているn関数呼び出しを、そしてdo.callただ一つの関数呼び出しがあります。だから、do.callかなり異なっていますlapply。これで問題が明確になることを願っています。

コード例:

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

そして:

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

25

最も簡単な言葉で:

  1. lapply()は、リスト内の各要素に特定の関数を適用するため、いくつかの関数呼び出しがあります。

  2. do.call()は、与えられた関数をリスト全体に適用するため、関数呼び出しは1つだけです。

学ぶ最良の方法は、Rのドキュメントにある関数の例をいじることです。


12

lapply()マップのような関数です。do.call()違います。引数を列挙するのではなく、リスト形式で関数に渡すために使用されます。例えば、

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

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の戻り値の型は、実行される関数によって異なります。


5

両者の違いは次のとおりです。

lapply(1:n,function,parameters)

=>これは1、パラメータを関数に送信=>これは2、パラメータを関数に送信、など

do.call 

1…nをベクトルとして送信し、機能するパラメータを送信するだけです

したがって、applyではn個の関数呼び出しがあり、do.callでは1つしかありません

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.