有没有办法在purrr :: map中自动传播NULL?

时间:2018-04-27 08:11:58

标签: r functional-programming tidyverse purrr

我有一些数据,其中一些是复制的,一些不是。我只能适应 我的复制数据模型。

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})

过了一会儿,我设法将这种行为提取到一个purrr风格的副词 函数,它采取另一个函数并包装它,使这种行为 NULL元素是自动的:

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

然而,这让我想知道:我是否重复行为 已经使用tidyverse函数进行调整?

额外问题:函数式编程中是否有maybe这样的函数?

这是测试我的副词的一个例子:

简单模型:环境A中数据的均值,没有数据模型 环境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很有用。这样的事情是否已经存在 在tidyverse?

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 :(得分:3)

你可以使用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)))