J'apprends R récemment et confondu par deux fonctions: lapply
et do.call
. Il semble qu’elles soient similaires à la fonction map
dans LISP. Mais pourquoi y a-t-il deux fonctions avec un nom si différent? Pourquoi R n'utilise-t-il pas simplement une fonction appelée map
?
Il existe une fonction appelée Map
qui peut être similaire à mapper dans d'autres langues:
lapply
renvoie une liste de la même longueur que X, chaque élément résultant de l'application de FUN à l'élément correspondant de X.
do.call
construit et exécute un appel de fonction à partir d'un nom ou d'une fonction et d'une liste d'arguments à lui transmettre.
Map
applique une fonction aux éléments correspondants de vecteurs donnés ... Map
est un simple wrapper pour mapply
qui ne tente pas de simplifier le résultat, semblable au mapcar de Common LISP (avec les arguments en cours de recyclage, cependant). Les versions futures peuvent permettre un certain contrôle du type de résultat.
Map
est un wrapper autour de mapply
lapply
est un cas particulier de mapply
Map
et lapply
seront similaires dans de nombreux cas.Par exemple, voici lapply
:
lapply(iris, class)
$Sepal.Length
[1] "numeric"
$Sepal.Width
[1] "numeric"
$Petal.Length
[1] "numeric"
$Petal.Width
[1] "numeric"
$Species
[1] "factor"
Et la même chose avec 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
prend une fonction en entrée et éclabousse ses autres arguments à la fonction. Il est largement utilisé, par exemple, pour assembler des listes en structures plus simples (souvent avec rbind
ou cbind
).
Par exemple:
x <- lapply(iris, class)
do.call(c, x)
Sepal.Length Sepal.Width Petal.Length Petal.Width Species
"numeric" "numeric" "numeric" "numeric" "factor"
lapply
applique une fonction sur une liste, do.call
appelle une fonction avec une liste d'arguments. Cela ressemble à une différence pour moi ...
Pour donner un exemple avec une liste:
X <- list(1:3,4:6,7:9)
Avec lapply, vous obtenez la moyenne de chaque élément de la liste comme ceci:
> lapply(X,mean)
[[1]]
[1] 2
[[2]]
[1] 5
[[3]]
[1] 8
do.call
donne une erreur, comme mean s'attend à ce que l'argument "trim" soit égal à 1.
D'autre part, rbind
lie tous les arguments ligne par ligne. Donc, pour lier X par rangée, vous faites:
> do.call(rbind,X)
[,1] [,2] [,3]
[1,] 1 2 3
[2,] 4 5 6
[3,] 7 8 9
Si vous utilisiez lapply
, R appliquerait rbind
à chaque élément de la liste, ce qui vous donnerait ce non-sens:
> 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
Pour avoir quelque chose comme Map, vous avez besoin de ?mapply
, ce qui est tout à fait différent. Pour obtenir par exemple la moyenne de chaque élément dans X, mais avec un ajustement différent, vous pouvez utiliser:
> mapply(mean,X,trim=c(0,0.5,0.1))
[1] 2 5 8
lapply
est similaire à map
, do.call
n'est pas. lapply
applique une fonction à tous les éléments d'une liste, do.call
appelle une fonction où tous les arguments de la fonction sont dans une liste. Ainsi, pour une liste d'éléments n
, lapply
a n
appels de fonction et do.call
n'a qu'un seul appel de fonction. Alors do.call
est assez différent de lapply
. J'espère que cela clarifie votre problème.
Un exemple de code:
do.call(sum, list(c(1, 2, 4, 1, 2), na.rm = TRUE))
et:
lapply(c(1, 2, 4, 1, 2), function(x) x + 1)
En termes simples:
lapply () applique une fonction donnée pour chaque élément de la liste. Il y aura donc plusieurs appels de fonction.
do.call () applique une fonction donnée à la liste dans son ensemble, de sorte qu'il n'y a qu'un seul appel de fonction.
La meilleure façon d'apprendre consiste à jouer avec les exemples de fonctions de la documentation R.
lapply()
est une fonction semblable à une carte. do.call()
est différent. Il est utilisé pour transmettre les arguments à une fonction sous forme de liste au lieu de les énumérer. Par exemple,
> do.call("+",list(4,5))
[1] 9
Bien qu'il y ait eu beaucoup de réponses, voici mon exemple à titre de référence. Supposons que nous ayons une liste de données comme:
L=list(c(1,2,3), c(4,5,6))
La fonction lapply renvoie une liste.
lapply(L, sum)
Ce qui précède signifie quelque chose comme ci-dessous.
list( sum( L[[1]]) , sum( L[[2]]))
Faisons maintenant la même chose pour do.call
do.call(sum, L)
Ça veut dire
sum( L[[1]], L[[2]])
Dans notre exemple, il retourne 21. En bref, lapply renvoie toujours une liste, tandis que le type de retour de do.call dépend réellement de la fonction exécutée.
La différence entre les deux sont:
lapply(1:n,function,parameters)
=> Cet envoi 1, paramètres à fonction => ceci envoie 2, paramètres à fonction et ainsi de suite
do.call
Envoie simplement 1… n en tant que vecteur et paramètres pour fonctionner
Donc, en appliquant vous avez n appels de fonction, en do.call vous n’avez qu’un seul