Я недавно изучаю R и смущен двумя функциями: lapply
и do.call
. Кажется, что они просто похожи на map
функции в Лиспе. Но почему две функции с такими разными именами? Почему R просто не использует вызываемую функцию map
?
источник
Я недавно изучаю R и смущен двумя функциями: lapply
и do.call
. Кажется, что они просто похожи на map
функции в Лиспе. Но почему две функции с такими разными именами? Почему R просто не использует вызываемую функцию map
?
Вызывается функция, Map
которая может быть похожа на map на других языках:
lapply
возвращает список той же длины, что и X, каждый элемент которого является результатом применения FUN к соответствующему элементу X.
do.call
конструирует и выполняет вызов функции из имени или функции и списка аргументов, которые ей передаются.
Map
применяет функцию к соответствующим элементам заданных векторов ... Map
- это простая оболочка, для mapply
которой не делается попыток упростить результат, как в случае с mapcar в 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"
do.call
почти то же самое, что иapply
в Лиспеdo.call(cbind, x)
в текущей версииError in do.call(c, x) : 'what' must be a function or character string
...cbind()
отличается от функцииc()
, и хотя это тоже работает, дает разные результаты.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
источник
lapply
похоже наmap
,do.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)
источник
Проще говоря:
lapply () применяет заданную функцию для каждого элемента в списке, поэтому будет несколько вызовов функций.
do.call () применяет данную функцию к списку в целом, поэтому есть только один вызов функции.
Лучший способ научиться - поиграть с примерами функций в документации R.
источник
Хотя было много ответов, вот мой пример для справки. Предположим, у нас есть список данных как:
L=list(c(1,2,3), c(4,5,6))
Функция lapply возвращает список.
Вышеупомянутое означает что-то вроде ниже.
list( sum( L[[1]]) , sum( L[[2]]))
Теперь сделаем то же самое для do.call.
Это значит
sum( L[[1]], L[[2]])
В нашем примере он возвращает 21. Короче говоря, lapply всегда возвращает список, а тип возврата do.call действительно зависит от выполняемой функции.
источник
lapply()
это функция, подобная карте.do.call()
отличается. Он используется для передачи аргументов функции в виде списка вместо их перечисления. Например,> do.call("+",list(4,5)) [1] 9
источник
Разница между ними:
lapply(1:n,function,parameters)
=> Это отправляет 1, параметры функции => это отправляет 2, параметры функции и т. Д.
Просто отправляет 1… n как вектор и параметры функции
Итак, в apply у вас есть n вызовов функций, в do.call у вас всего один
источник