R purrr 捕获输入和输出
R purrr capture input and outputs
也许这更像是日志记录而不只是函数式编程,但我想知道是否有更 purrr
的方法来实现输入消息和 outputs/diagnostic 消息。
这对我很有用,因为我想在生产中使用 sparklyr
并记录分区查询的作业状态。
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
}
所有这一切都在做一个 table 的行式作业来调度和返回带有诊断消息的作业。这被转储到日志中,因此如果出现故障,我可以检查哪个作业失败了。
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
一起玩得很好。
如有任何关于如何更好地完成此操作的建议,我们将不胜感激。谢谢
除非我遗漏了什么,否则可以简单地重写为:
cross(list(query = functions, params = param)) %>%
map(~ c(.x, adjective(eval(parse(text = .x$query)))(.x$param)))
我不知道为什么你 transpose()
cross()
的输出然后 map2()
在它上面,在 [=15= 之后直接 map()
似乎更简单].
此外,您真的希望您的函数仅具有通过 str()
和 return NULL
打印内容的副作用吗?
我建议宁愿 return 你的列表,然后调用 str()
函数的结果。
类似于:
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()
。它可以很容易地调整)
# 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)
# ...
此外,我不确定您所说的 "play nice with quietly()
" 是什么意思。起初我担心我会遇到懒惰评估的问题,但我没有。
如果您想使用 invoke()
,可以将函数中的 map2(df$f, df$param, ~ .x(.y))
行替换为 invoke_map()
:
all.equal(
purrr::map2(df$f, df$param, ~ .x(.y)),
invoke_map(df$f, df$param)
)
# [1] TRUE
也许这更像是日志记录而不只是函数式编程,但我想知道是否有更 purrr
的方法来实现输入消息和 outputs/diagnostic 消息。
这对我很有用,因为我想在生产中使用 sparklyr
并记录分区查询的作业状态。
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
}
所有这一切都在做一个 table 的行式作业来调度和返回带有诊断消息的作业。这被转储到日志中,因此如果出现故障,我可以检查哪个作业失败了。
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
一起玩得很好。
如有任何关于如何更好地完成此操作的建议,我们将不胜感激。谢谢
除非我遗漏了什么,否则可以简单地重写为:
cross(list(query = functions, params = param)) %>%
map(~ c(.x, adjective(eval(parse(text = .x$query)))(.x$param)))
我不知道为什么你 transpose()
cross()
的输出然后 map2()
在它上面,在 [=15= 之后直接 map()
似乎更简单].
此外,您真的希望您的函数仅具有通过 str()
和 return NULL
打印内容的副作用吗?
我建议宁愿 return 你的列表,然后调用 str()
函数的结果。
类似于:
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()
。它可以很容易地调整)
# 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)
# ...
此外,我不确定您所说的 "play nice with quietly()
" 是什么意思。起初我担心我会遇到懒惰评估的问题,但我没有。
如果您想使用 invoke()
,可以将函数中的 map2(df$f, df$param, ~ .x(.y))
行替换为 invoke_map()
:
all.equal(
purrr::map2(df$f, df$param, ~ .x(.y)),
invoke_map(df$f, df$param)
)
# [1] TRUE