Я вивчаю R нещодавно і мене бентежать дві функції: lapply
і do.call
. Здається, вони "просто схожі на map
функція в Lisp. Але чому існують дві функції з такою різною назвою? Чому просто не використовується функція, яка називається map
?
Відповіді:
100 для відповіді № 1Існує функція, яка називається Map
що може бути схожим на карту іншими мовами:
lapply
повертає список тієї ж довжини, що і X, кожен елемент якого є результатом застосування FUN до відповідного елемента X.do.call
конструює та виконує виклик функції з імені або функції та списку аргументів, які повинні бути передані їй.Map
застосовує функцію до відповідних елементів заданих векторів ...Map
є простою обгорткоюmapply
який не намагається спростити результат, подібно до карти мапа Common Lisp (однак аргументи переробляються, однак). Майбутні версії можуть дозволити певний контроль над типом результату.
Map
- це обгортка навколоmapply
lapply
це особливий випадокmapply
- Тому
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"
І те саме використовуючи 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"
51 за відповідь № 2
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
пов'язує всі аргументи rowwise. Отже, щоб пов’язати X rowwise, ви робите:
> 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
28 для відповіді № 3
lapply
схоже на map
, do.call
не. lapply
застосовує функцію до всіх елементів списку, do.call
викликає функцію, де всі аргументи функції знаходяться у списку. Отже для a 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)
20 за відповідь № 4
Найпростішими словами:
lapply ()</ strong> застосовує задану функцію до кожного елемента у списку, тому буде декілька викликів функцій.
do.call ()</ strong> застосовує дану функцію до списку в цілому, тому є лише один виклик функції.
Найкращий спосіб навчитися - це пограти з прикладами функцій у документації R.
12 за відповіддю № 5
lapply()
є картоподібною функцією. do.call()
інакший. Він використовується для передачі аргументів функції у формі списку, а не для їх перерахування. Наприклад,
> do.call("+",list(4,5))
[1] 9
8 для відповіді № 6
Хоча відповідей було багато, ось мій приклад для довідки. Припустимо, у нас є список даних як:
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 за відповідь № 7
Різниця між ними:
lapply(1:n,function,parameters)
=> Це посилання 1, параметри для функціонування => це посилає 2, параметри для функціонування і так далі
do.call
Просто надсилає 1… n як вектор і параметри для функціонування
Отже, у застосунку у вас є n викликів функцій, у do.call - лише один