首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >R purrr捕获输入和输出

R purrr捕获输入和输出
EN

Stack Overflow用户
提问于 2017-03-14 20:04:42
回答 1查看 176关注 0票数 0

也许这更像是日志,而不仅仅是函数式编程,但我想知道是否有更像purrr的方式来实现输入和输出/诊断消息的消息。

这对我很有用,因为我想在生产中使用sparklyr,并对分区查询的作业状态进行记录。

代码语言:javascript
复制
library(magrittr)

# Helper to list input params with output
helper = function(x, y, z) {
  c(query = x, params = y, z) 
}

# For single parameters
log_results = function(param, functions, adjective) {

  # Cross the input vectors to apply each function to each parameter set
  crossed_args = purrr::transpose(purrr::cross2(param, functions))
  crossed_params = crossed_args[[1]] %>% unlist
  crossed_function_names = crossed_args[[2]] %>% unlist()

  # Parse to the query to wrap it with quietly
  parsed_functions = purrr::map(crossed_function_names, ~ adjective(eval(parse(text = .x))))

  # Tidy container for function calls
  df = dplyr::data_frame(function_name = crossed_function_names, f = parsed_functions, param = crossed_params)
  # Execute to get query results
  results_log = purrr::map2(df$f, df$param, ~ .x(.y))

  # Output results log as message
  purrr::pmap(.l = list(df$function_name, df$param, results_log), helper) %>% str

}

所有这些操作都是创建一个逐行作业的表,以便分派并返回带有诊断消息的作业。它被转储到日志中,因此如果出现故障,我可以检查哪个作业失败了。

代码语言:javascript
复制
log_results_quietly = purrr::partial(log_results, adjective = purrr::quietly)

> log_results_quietly(c(-1, 3, 4, 5), c("exp", "log"))
List of 8
 $ :List of 6
  ..$ query   : chr "exp"
  ..$ params  : num -1
  ..$ result  : num 0.368
  ..$ output  : chr ""
  ..$ warnings: chr(0) 
  ..$ messages: chr(0) 
 $ :List of 6
  ..$ query   : chr "exp"
  ..$ params  : num 3
  ..$ result  : num 20.1
  ..$ output  : chr ""
  ..$ warnings: chr(0) 
  ..$ messages: chr(0) 
 $ :List of 6
  ..$ query   : chr "exp"
  ..$ params  : num 4
  ..$ result  : num 54.6
  ..$ output  : chr ""
  ..$ warnings: chr(0) 
  ..$ messages: chr(0) 
...

我认为invoke可能会有所帮助,但我不能让它与quietly友好相处。

任何关于如何更好地做到这一点的建议都是值得感谢的。谢谢

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2017-04-03 23:27:00

除非我遗漏了什么,否则它可以像这样简单地重写:

代码语言:javascript
复制
cross(list(query = functions, params = param)) %>% 
  map(~ c(.x, adjective(eval(parse(text = .x$query)))(.x$param)))

我不明白为什么你先transpose() cross()的输出,然后再map2()它,在cross()之后直接map()似乎更简单。

另外,您真的希望您的函数只具有通过str()打印内容并返回NULL的副作用吗?我建议您返回列表,然后根据函数的结果调用str()

类似于:

代码语言:javascript
复制
log_results_2 <- function(param, functions, adjective) {
  cross(list(query = functions, params = param)) %>% 
    map(~ c(.x, adjective(eval(parse(text = .x$query)))(.x$param)))
}
log_results_quietly_2 = purrr::partial(log_results_2, adjective = purrr::quietly)
res <- log_results_quietly_2(c(-1, 3, 4, 5), c("exp", "log"))
str(res)

(请注意,它的顺序与您的不同,因为我首先使用functions调用了cross()。它可以很容易地调整)

代码语言:javascript
复制
# List of 8
#  $ :List of 6
#   ..$ query   : chr "exp"
#   ..$ params  : num -1
#   ..$ result  : num 0.368
#   ..$ output  : chr ""
#   ..$ warnings: chr(0) 
#   ..$ messages: chr(0) 
#  $ :List of 6
#   ..$ query   : chr "log"
#   ..$ params  : num -1
#   ..$ result  : num NaN
#   ..$ output  : chr ""
#   ..$ warnings: chr "production de NaN"
#   ..$ messages: chr(0) 
#  $ :List of 6
#   ..$ query   : chr "exp"
#   ..$ params  : num 3
#   ..$ result  : num 20.1
#   ..$ output  : chr ""
#   ..$ warnings: chr(0) 
#   ..$ messages: chr(0) 
# ...

我也不确定你说的“和quietly()玩得好”是什么意思。一开始我担心我会在懒惰的评估上遇到问题,但我没有。

如果您想使用invoke(),可以使用invoke_map()替换函数中的map2(df$f, df$param, ~ .x(.y))

代码语言:javascript
复制
all.equal(
  purrr::map2(df$f, df$param, ~ .x(.y)),
  invoke_map(df$f, df$param)
)
# [1] TRUE
票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/42785537

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档