Jaka jest różnica między lapply a do.zadzwonić?

Ostatnio uczę się R i jestem zdezorientowany przez dwie funkcje: lapply i do.call. Wygląda na to, że są one po prostu podobne do funkcji map w Lispie. Ale dlaczego istnieją dwie funkcje o tak innej nazwie? Dlaczego R nie używa funkcji o nazwie map?

Author: Uwe Keim, 2012-05-29

7 answers

Istnieje funkcja o nazwie Map, która może być podobna do map w innych językach:

  • lapply zwraca listę o tej samej długości co X, której każdy element jest wynikiem zastosowania FUN do odpowiadającego mu elementu X.

  • do.call konstruuje i wykonuje wywołanie funkcji z nazwy lub funkcji oraz listy argumentów, które mają być do niej przekazane.

  • Map stosuje funkcję do odpowiednich elementów danych wektorów... Map jest prosty wrapper do mapply, który nie próbuje uprościć wyniku, podobny do mapcar Common Lispu (z argumentami jednak poddanymi recyklingowi). Przyszłe wersje mogą pozwolić na pewną kontrolę typu wyniku.


  1. Map jest owijką wokół mapply
  2. lapply jest szczególnym przypadkiem mapply
  3. dlatego Map i lapply będą podobne w wielu przypadkach.

Na przykład, oto lapply:

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

$Sepal.Width
[1] "numeric"

$Petal.Length
[1] "numeric"

$Petal.Width
[1] "numeric"

$Species
[1] "factor"

I to samo za pomocą 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 przyjmuje funkcję jako wejście i przekazuje jej inne argumenty do funkcji. Jest szeroko stosowany, na przykład, do łączenia list w prostsze struktury (często z rbind lub cbind).

Na przykład:

x <- lapply(iris, class)
do.call(c, x)
Sepal.Length  Sepal.Width Petal.Length  Petal.Width      Species 
   "numeric"    "numeric"    "numeric"    "numeric"     "factor" 
 131
Author: Andrie,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-05-29 15:37:35

lapply stosuje funkcję nad listą, do.call wywołuje funkcję z listą argumentów. Dla mnie to wygląda na sporą różnicę...

Aby podać przykład z listą:

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

Z lapply otrzymujesz średnią każdego elementu na liście w następujący sposób:

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

[[2]]
[1] 5

[[3]]
[1] 8

do.call podaje błąd, ponieważ mean oczekuje, że argument "trim" będzie równy 1.

Z drugiej strony rbind wiąże wszystkie argumenty w wierszu. Więc aby związać x wierszem, robisz :

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

Jeśli użyłbyś lapply, R zastosowałby rbind do każdego elementu listy, dając Ci ten nonsens:

> 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

Aby mieć coś takiego jak mapa, potrzebujesz ?mapply, co jest czymś zupełnie innym. Aby uzyskać np. średnią każdego elementu w X, ale z innym przycinaniem, można użyć :

> mapply(mean,X,trim=c(0,0.5,0.1))
[1] 2 5 8
 64
Author: Joris Meys,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-05-29 15:11:51

lapply jest podobny do map, do.call nie jest. lapply stosuje funkcję do wszystkich elementów listy, do.call wywołuje funkcję, w której wszystkie argumenty funkcji znajdują się na liście. Tak więc dla listy elementów n lapply ma wywołania funkcji n, a do.call ma tylko jedno wywołanie funkcji. Więc {[4] } jest zupełnie inna od lapply. Mam nadzieję, że to wyjaśni twój problem.

Przykład kodu:

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

I:

lapply(c(1, 2, 4, 1, 2), function(x) x + 1)
 37
Author: Paul Hiemstra,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-12-19 02:59:53

W najprostszych słowach:

  1. lapply() stosuje daną funkcję dla każdego elementu na liście, więc będzie kilka wywołań funkcji.

  2. zrób.call() stosuje daną funkcję do listy jako całości, więc jest tylko jedno wywołanie funkcji.

Najlepszym sposobem na naukę jest pobawienie się przykładami funkcji w dokumentacji R.

 29
Author: LoveMeow,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-11-24 16:19:01

Chociaż było wiele odpowiedzi, oto mój przykład odniesienia. Załóżmy, że mamy listę danych jako:

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

Funkcja lapply zwraca listę.

lapply(L, sum) 

Powyższe oznacza coś takiego jak poniżej.

list( sum( L[[1]]) , sum( L[[2]]))
[[5]}teraz zróbmy to samo dla zrobić.call
do.call(sum, L) 

To znaczy

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

W naszym przykładzie zwraca 21. Krótko mówiąc, lapply zawsze zwraca listę, podczas gdy typ zwracania do.wywołanie zależy od wykonanej funkcji.

 15
Author: kimman,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-06-02 16:57:15

lapply() jest funkcją podobną do mapy. do.call() jest inny. Jest on używany do przekazywania argumentów do funkcji w formie listy zamiast ich wyliczania. Na przykład,

> do.call("+",list(4,5))
[1] 9
 12
Author: frankc,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-05-29 15:34:42

Różnica między nimi to:

lapply(1:n,function,parameters)

= > This send 1, parameters to function = > to wysyła 2, parametry do funkcji i tak dalej

do.call 

Po prostu wysyła 1 ... n jako wektor i parametry do funkcji

Więc w apply masz n wywołań funkcji, w do.call you have just one

 6
Author: nitin lal,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-08-16 10:25:57