Зачем использовать purrr:: map вместо lapply?
есть ли причина, почему я должен использовать
map(<list-like-object>, function(x) <do stuff>)
вместо
lapply(<list-like-object>, function(x) <do stuff>)
результат должен быть таким же, и тесты, которые я сделал, похоже, показывают, что lapply немного быстрее (это должно быть как map необходимо оценить все нестандартные оценки ввода).
так есть ли причина, почему для таких простых случаев я должен на самом деле рассмотреть вопрос о переходе на purrr::map? Я не спрашиваю здесь о своих симпатиях или антипатиях о синтаксисе, другом функциональные возможности, предоставляемые purrr и т. д., но строго о сравнении purrr::map С lapply предполагая использование стандартной оценки, т. е. map(<list-like-object>, function(x) <do stuff>). Есть ли какое-либо преимущество, что purrr::map в плане производительности, обработки исключений и т. д.? Комментарии ниже предполагают, что это не так, но, может быть, кто-то может разработать немного больше?
3 ответов:
Если единственная функция, которую вы используете из purrr-это
map(), то нет, преимущества не являются существенными. Как отмечает Рич Паулу, главное преимуществоmap()- это помощники, которые позволяют писать компактный код для общих особых случаев:
~ . + 1эквивалентноfunction(x) x + 1
list("x", 1)эквивалентноfunction(x) x[["x"]][[1]]. Эти помощники немного более общие, чем[[- см.?pluckдля сведения. Для сведения прямоугольник, С каждого.dir("\.csv$") %>% set_names() %>% map(read.csv) %>% imap(~ transform(.x, filename = .y))
walk()возвращает его вход невидимо; и полезно, когда вы вызов функции для ее побочных эффектов (т. е. запись файлов в диск.)не говоря уже о других помощниках, таких как
safely()иpartial().лично я считаю, что когда я использую purrr, я могу написать функциональный код с меньшим трением и большей легкостью; он уменьшает зазор между размышляющий идею и ее реализацию. Но ваш пробег может варьироваться; там нет необходимости использовать муррр, если это на самом деле не поможет вам.
Microbenchmarks
да
map()немного медленнее, чемlapply(). Но стоимость использованияmap()илиlapply()управляется тем, что вы отображаете, а не накладные расходы выполнения цикла. В микротестов производительности ниже предполагают, что стоимость изmap()по сравнению сlapply()составляет около 40 НС на элемент, который кажется маловероятным, чтобы существенно повлиять большинство кода Р.library(purrr) n <- 1e4 x <- 1:n f <- function(x) NULL mb <- microbenchmark::microbenchmark( lapply = lapply(x, f), map = map(x, f) ) summary(mb, unit = "ns")$median / n #> [1] 490.343 546.880
этот онлайн учебник purrr подчеркивает удобство не нужно явно выписывать анонимные функции при использовании purrr, что наряду с функциями карты типа делает его очень функциональным.
1. purrr::карта синтаксически гораздо удобнее, чем lapply
извлечь второй элемент списка
map(list, 2) # and it's done like magicчто, как указал @F. Privé, то же самое как:
map(list, function(x) x[[2]])С lapply
lapply(list, 2) # doesn't workнам нужно передать ему анонимную функцию
lapply(list, function(x) x[[2]]) # now it worksили, как указал @RichScriven, мы можем просто пройти
[[как аргумент в лаплиlapply(list, `[[`, 2) # a bit more simple syntanticallyв фоновом режиме purr принимает в качестве аргумента числовой или символьный вектор и использует его в качестве функции подмножества. Если вы делаете много и много подмножеств списки с использованием lapply и tire либо определяют пользовательскую функцию, либо пишут анонимную функцию для подмножества, удобство является одной из причин перехода к purrr.
2. Тип-специфические функции карты просто много строк кода
- map_chr ()
- map_lgl ()
- map_int ()
- map_dbl ()
- map_df () - мой любимый, возвращает фрейм данных.
каждая из этих тип-специфических функций карты возвращает атомарный список, а не список, который
map()иlapply()автоматически вернуться. Если вы имеете дело с вложенными списками, которые имеют атомарные векторы внутри, вы можете использовать эти специфические для типа функции карты, чтобы вытащить векторы напрямую или принудить векторы к векторам int, dbl, chr. Еще один момент для удобства и функциональности.3. Удобство в сторону, lapply быстрее, чем карта.
используя функции удобства purrr, как указал @F. Privé замедляет вниз обработки немного. Давайте рассмотрим каждый из 4 случаев, которые я представил выше.
# devtools::install_github("jennybc/repurrrsive") library(repurrrsive) library(purrr) library(microbenchmark) library(ggplot2) mbm <- microbenchmark( lapply = lapply(got_chars[1:4], function(x) x[[2]]), lapply_2 = lapply(got_chars[1:4], `[[`, 2), map_shortcut = map(got_chars[1:4], 2), map = map(got_chars[1:4], function(x) x[[2]]), times = 100 ) autoplot(mbm)и победитель....
lapply(list, `[[`, 2)в общем, если скорость-это то, что вам нужно:base:: lapply
если простой синтаксис-это ваш джем: purrr::карта
если мы не рассматриваем аспекты вкуса (в противном случае этот вопрос должен быть закрыт) или последовательность синтаксиса, стиль и т. д., Ответ Нет, нет особой причины использовать
mapвместоlapplyили другие варианты семейства apply, такие как strictervapply.PS: Для тех людей, которые безвозмездно downvoting, просто помните, что OP написал:
Я не спрашиваю здесь о своих симпатиях или антипатиях о синтаксисе, другой функциональные возможности, предоставляемые purrr и т. д. но строго о сравнение purrr:: map с lapply предполагая использование стандарта оценка
если вы не рассматриваете синтаксис или другие функциональные возможности
purrr, нет никакой особой причины использоватьmap. Я используюpurrrЯ и я в порядке с ответом Хэдли, но он иронично проходит через те самые вещи, которые ОП заявил заранее, что он не спрашивал.

Comments