web-dev-qa-db-ja.com

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

私は最近Rを学んでおり、2つの関数lapplydo.callで混乱しています。これらは、LISPのmap関数に似ているようです。しかし、なぜそのような異なる名前を持つ2つの関数があるのでしょうか? Rがmapという関数を使用しないのはなぜですか?

126
Hanfei Sun

Mapという関数があり、他の言語のmapに似ている場合があります。

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

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

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


  1. Mapmapplyのラッパーです
  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" 
112
Andrie

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

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

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

lapplymapに似ていますが、do.callは似ていません。 lapplyはリストのすべての要素に関数を適用し、do.callはすべての関数引数がリストにある関数を呼び出します。したがって、n要素リストの場合、lapplyにはn関数呼び出しがあり、do.callには1つの関数呼び出ししかありません。したがって、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)
30
Paul Hiemstra

最も簡単な言葉で:

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

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

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

24
LoveMeow

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

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

多くの回答がありましたが、参考のために私の例を示します。次のようなデータのリストがあるとします:

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の戻り値の型は実際に実行される関数に依存します。

10
kimman

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

lapply(1:n,function,parameters)

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

do.call 

関数として1 ... nをベクトルとパラメーターとして送信するだけです

したがって、適用ではn個の関数呼び出しがあり、do.callでは1つだけです

5
nitin lal