purrr объединяет pmap и nest

#r #purrr

#r #purrr

Вопрос:

Я пытаюсь научиться purrr моделировать данные с использованием rnorm с различными средствами, sd и n на каждой итерации. Этот код генерирует мой фрейм данных:

 parameter = crossing(n = c(60,80,100),   
                    agegroup = c("a", "b","c"), 
                    effectsize = c(0.2, 0.5, 0.8),
                    sd =2
                        ) %>%
# create a simulation id number
group_by(agegroup) %>%
mutate(sim= row_number())%>%
ungroup() %>%
mutate(# change effect size so that one group has effect, others d=0
       effectsize= if_else(agegroup == "a", effectsize, 0),
       # calculate the mean for the distribution from effect size
       mean =effectsize*sd) 
  

Теперь я хочу повторить различные симуляции и для каждой строки сгенерировать данные в соответствии со средним значением, sd и r, используя rnorm

 # create a nested dataframe to iterate over each simulation and agegroup
nested_df =  parameter %>%
  group_by(sim, agegroup, effectsize)%>%
  nest() %>% arrange(sim)
  

Вот как тогда выглядит мой фрейм данных:
изображение фрейма данных

Теперь я хочу создать нормально распределенные данные со средним значением, sd и n, указанными в столбце «данные»

 nested_df = nested_df %>%  
  mutate(data_points = pmap(data,rnorm))
  

Однако приведенный выше код выдает ошибку, для которой я не смог найти решение:

 Error in mutate_impl(.data, dots) : 
  Evaluation error: unused arguments 
  

Я прочитал главу об итерации в R for Data Science и погуглил кучу, но я не могу понять, как объединить pmap и nest. Причина, по которой я хотел бы использовать эти функции, заключается в том, что это упростило бы хранение параметров, смоделированных данных и выходных данных в одном фрейме данных.

Ответ №1:

Вам не обязательно вкладывать параметры. Например:

 parameter %>%
  # Use `pmap` because we explicitly specify three arguments
  mutate(data_points = pmap(list(n, mean, sd), rnorm))
# A tibble: 27 x 7
#         n agegroup effectsize    sd   sim  mean data_points
#     <dbl> <chr>         <dbl> <dbl> <int> <dbl> <list>     
#   1    60 a               0.2     2     1   0.4 <dbl [60]> 
#   2    60 a               0.5     2     2   1   <dbl [60]> 
#   3    60 a               0.8     2     3   1.6 <dbl [60]> 
  

С вложенным фреймом данных вы можете использовать map вместо pmap :

 nested_df %>%
  # Use `map` because there is really one argument, `data`,
  # but then refer to three different columns of `data`.
  mutate(data_points = map(data, ~ rnorm(.$n, .$mean, .$sd)))
  

Ответ №2:

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

 x <- tibble(n = 100, mean = 5, sd = 0.1)
pmap(x, rnorm)
  

что очень похоже на использование do.call :

 do.call(rnorm, x)
  

Однако, если вы хотите использовать pmap inside mutate , вы приводите входные данные для функции .f в правильную форму.
Написание

 nested_df %>% 
  mutate(y = pmap(x, f))
  

означает, что f ожидается ввод x .
В вашем случае rnorm ожидает три входных данных, но получает только один.

Итак, если вы настаиваете на вложенности входных данных, вы можете сделать это:

 nested_df %>%  
  mutate(data_points = pmap(list(data), function(z) pmap(z, rnorm))[[1]])
  

или

    nested_df %>%  
      mutate(data_points = pmap(list(data), function(z) do.call(rnorm, z))).
  

Однако я бы рекомендовал сделать это немного по-другому:

 parameter %>% 
  mutate(data_points = pmap(list(n, mean, sd), rnorm))
  

Надеюсь, это немного поможет.