Предоставление аргумента списка .l в pmap () или pwalk () - PullRequest
0 голосов
/ 27 ноября 2018

Мне неясно, когда аргументы могут быть явно спарены в аргументах pmap () и pwalk () .l.Иногда кажется, что эти функции мурлыкания работают только тогда, когда предоставленный им фрейм данных имеет имена, которые отображаются непосредственно в ожидаемые аргументы функции, названной в .f.В других случаях в pmap () может быть предоставлен полный фрейм данных, а переменные могут быть отображены в пару явно.

library(dplyr)
library(purrr)
library(tibble)

set.seed(57)

ds_mt <- 
  mtcars %>% 
  rownames_to_column("model") %>% 
  mutate(am = factor(am, labels = c("auto", "manual"))) %>% 
  select(model, mpg, wt, cyl, am) %>% 
  sample_n(3)

foo <- function(model, am, mpg){
  print(
    paste("The", model, "has a", am, "transmission and gets", mpg, "mpgs.")
  )
}

Почему эти куски кода работают?

ds_mt %>% 
  select(model, am, mpg) %>% 
  pwalk(
  .l = .,
  .f = foo
)

# example with explicit pair mapping
ds_mt %>% 
  mutate(
    new_var = 
      pmap(
        .l = list(model=model, am=am, mpg=mpg),
        .f = foo
      )
  )

Пока эти куски кода не работают?

ds_mt %>% 
  pwalk(
  .l = list(model, am, mpg),
  .f = foo
)

ds_mt %>% 
  pwalk(
  .l = list(model=model, am=am, mpg=mpg),
  .f = foo
)

1 Ответ

0 голосов
/ 27 ноября 2018

Ваша проблема не имеет ничего общего с pmap() или pwalk().Это связано с некоторым неправильным пониманием того, как труба и функция mutate() работают.


Во-первых, труба:

Если иное не указано точкой, труба проходит LHS какпервый аргумент функции в RHS.

Так что это работает:

ds_mt %>% 
  select(model, am, mpg) %>% 
  pwalk(
    .l = .,
    .f = foo
  )

потому что ваш список (= ваш фрейм данных, поскольку фрейм данных является списком векторов), которыйLHS канала используется в качестве первого аргумента pwalk() в RHS.

В этом случае вам на самом деле не нужна точка, и вы могли бы написать ее гораздо проще:

ds_mt %>% 
  select(model, am, mpg) %>% 
  pwalk(foo)

С другой стороны, когда вы пытаетесь запустить:

ds_mt %>% 
  pwalk(
    .l = list(model, am, mpg),
    .f = foo
  )

соединение между вашей LHS и вашей RHS не соответствует правилам канала, поэтому R понятия не имеет, чтоmodel так как у вас нет объекта с именем model.

Чтобы это выражение работало, вы можете написать его без канала следующим образом:

pwalk(
  .l = list(ds_mt$model, ds_mt$am, ds_mt$mpg),
  .f = foo
)

Или, если вы хотите использовать трубу, вы должны заменить LHS трубы на точки (так какне передается в качестве первого аргумента функции в RHS), где это необходимо для работы кода, но здесь, поскольку вы передаете LHS внутри вложенных функций, вы также должны поместить RHS между фигурными скобками, потому что R будетв противном случае передайте LHS в качестве первого аргумента самой внешней функции RHS:

ds_mt %>% {
    pwalk(
      .l = list(.$model, .$am, .$mpg),
      .f = foo
    )
  }

или, в стиле немного более компактном:

ds_mt %>% {pwalk(list(.$model, .$am, .$mpg), foo)}

В заключение, этонедостаточно иметь объект на LHS трубы для того, чтобы R волшебным образом применил его в нужных местах RHS (но я думаю, что ваша путаница может возникнуть из-за функций dplyr (см. ниже)).По умолчанию он используется в качестве первого аргумента функции в RHS (и в этом случае вам не нужна точка).Для других мест размещения вам нужна точка в каждом месте, где требуется LHS.А в случае вложенных функций (как у вас здесь) вам также нужно заключить RHS в фигурные скобки, или R передаст LHS в качестве первого аргумента вашей самой внешней функции RHS.


Теперь к вашему mutate() примеру:

ds_mt %>% 
  mutate(
    new_var = 
      pmap(
        .l = list(model, am, mpg),
        .f = foo
      )
  )

Этот работает, потому что в более новых версиях dplyr фрейм данных и знак доллара больше не нужны при вызове переменных внутри mutate()функция.Итак, здесь R не задается вопросом, что такое model, потому что вы находитесь, так сказать, в «структуре мутирования», и R понимает model как значение .$model или ds_mt$model.Итак, здесь снова, это не имеет ничего общего с pmap() или pwalk(), но является особенностью функций dplyr (это было бы то же самое с summarise()).Я полагаю, что это сокращение обозначения, которое допускают функции dplyr, приводит вас к некоторым заблуждениям.


Наконец, то, что вы называете "явным сопоставлением пар", не имеет никакого эффекта.Поскольку вы определили свою функцию foo() как принимающую 3 аргумента, при условии, что вы сохраняете аргументы в правильном порядке,

foo(model = model, am = am, mpg = mpg)

и

foo(model, am, mpg)

абсолютно одинаковы.Однако если вы поменяете местами аргументы, вам нужно быть явным.Например:

foo(am = am, model = model, mpg = mpg)
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...