Есть ли способ автоматически распространять NULL в purrr :: map? - PullRequest
0 голосов
/ 27 апреля 2018

У меня есть некоторые данные, некоторые из которых реплицированы, некоторые нет. Я могу только соответствовать моя модель для реплицированных данных.

library(tidyverse)
d <- tribble(
  ~env, ~val,
  "A",  1,
  "A",  2,
  "B",  3
)

Я использую функции tidyr::nest() и purrr::map(), чтобы соответствовать моей модели. Однако в каждой функции, которую я использую для map(), мне приходилось случай, когда конкретный набор данных не моделируется, который я заархивировал через звонки в стиле

map(col, function(elem){ if(!is.null(elem)) DO_STUFF(elem) else NULL})

Через некоторое время мне удалось извлечь это поведение в наречие в стиле мурлыкания. функция, которая принимает другую функцию и упаковывает ее так, что это поведение для NULL элементов автоматически:

maybe <- function(fun){
  function(val,...){ if(!is.null(val)) fun(val, ...) else NULL}
}

Однако это заставило меня задуматься: Дублирую ли я поведение, которое уже архивируется с помощью функций Tidyverse?

Дополнительный вопрос: есть ли в функциональном программировании слово для такой функции, как maybe?


Вот пример, чтобы проверить мою наречие:

Простая модель: среднее значение для данных в среде А и отсутствие модели для данных в среда B (поскольку данные не реплицированы:)

modelFuns <- list(A = mean, B = NULL)

Сгруппируйте данные по среде и определите подходящую модель для каждой группы

d <- d %>% group_by(env) %>% nest(.key = "data")
d %<>% mutate(model = modelFuns[env])
d

## # A tibble: 2 x 3
##   env   data             model 
##   <chr> <list>           <list>
## 1 A     <tibble [2 × 1]> <fn>  
## 2 B     <tibble [1 × 1]> <NULL>

Выполнить моделирование:

d %<>% mutate(out = pmap(list(model, data), maybe(function(m,d) m(d$val))))
d

## # A tibble: 2 x 4
##   env   data             model  out      
##   <chr> <list>           <list> <list>   
## 1 A     <tibble [2 × 1]> <fn>   <dbl [1]>
## 2 B     <tibble [1 × 1]> <NULL> <NULL>

Что эквивалентно следующему коду, в котором не используется мое maybe наречие:

d %<>% mutate(out = pmap(list(model, data), function(m,d){if(!is.null(m)) m(d$val) else NULL}))
d

## # A tibble: 2 x 4
##   env   data             model  out      
##   <chr> <list>           <list> <list>   
## 1 A     <tibble [2 × 1]> <fn>   <dbl [1]>
## 2 B     <tibble [1 × 1]> <NULL> <NULL>

Факт, что может быть значение или может быть NULL, распространяется на все, что я хочу сделать с результатами моделирования вниз по течению, что почему наречие maybe полезно. Существует ли что-то подобное уже в тидиверсе?

isModelNice <- function(val) val > 0
d %<>% mutate(nice = map(out, maybe(isModelNice)))
d

## # A tibble: 2 x 5
##   env   data             model  out       nice     
##   <chr> <list>           <list> <list>    <list>   
## 1 A     <tibble [2 × 1]> <fn>   <dbl [1]> <lgl [1]>
## 2 B     <tibble [1 × 1]> <NULL> <NULL>    <NULL>

1 Ответ

0 голосов
/ 27 апреля 2018

не могли бы вы использовать purrr::possibly()?

library(tidyverse)

d <- tribble(
  ~env, ~val,
  "A",  1,
  "A",  2,
  "B",  3
)

modelFuns <- list(A = mean, B = NULL)

d %>% group_by(env) %>% 
  nest(.key = "data") %>% 
  mutate(model = modelFuns[env]) %>% 
  mutate(out = pmap(list(model, data), possibly(function(m,d) m(d$val), NULL)))
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...