R:以编程方式创建函数调用

Pet*_*eet 10 r lazy-evaluation dplyr

我经常需要在另一个函数内创建一个函数调用,然后进行评估.我倾向于使用eval(parse(text = "what_needs_to_be_done")) ,使用构造的文本paste0().但是,这并不是一种好方法.这是一个例子:

select_data <- function(x, A = NULL, B = NULL, C = NULL) {
  kall <- as.list(match.call())
  vars <- names(kall)[names(kall) %in% c("A", "B", "C")]
  selection_criteria <- paste0(vars,  " == ", kall[vars], collapse = ", ")
  txt <- paste0("dplyr::filter(x, ", selection_criteria, ")")
  res <- eval(parse(text = txt))
  return(res)
}   

DF <- data.frame(A = c(1,1,2,2,3,3), B = c(1,2,1,2,1,2), C = c(1,1,1,2,2,2))
select_data(DF, A = 2, C = 2)
Run Code Online (Sandbox Code Playgroud)

这只是一个例子,在大多数情况下,要构建的功能更复杂和更广泛.但是,该示例显示了一般问题.我现在做的首先paste0是函数调用,我在控制台输入它然后评估它的方式.

我已经篡改了与替代办法substitute,lazyeval,bquote,但我dont't很理解他们真正做的,因此不能让他们的工作.

你能帮助我找到一种更好的方法来构建呼叫并随后对其进行评估吗?

Pie*_*une 10

更新4.29.17 - 即将发布的dplyr 0.6.0将解决这些问题.以下问题增加了新的答案.有关使用dplyr进行编程的更多信息,请参阅此插图.


你有正确的想法.您可以稍微缩短代码?filter_和点参数...:

select_data <- function(x, ...) {
  kall <- list(...)
  filter_(.data=x, paste0(names(kall), "==", unlist(kall), collapse="&"))
}
select_data(DF, A = 2, C = 2)
#   A B C
# 1 2 2 2
Run Code Online (Sandbox Code Playgroud)

更新

dplyr即使对于中间编码器,编程也很具挑战性.作者承认,非标准评估的优势伴随着功能编程的难度.有许多SO用户遇到同样的问题:

dplyr中的标准评估

dplyr功能不起作用

在另一个函数中使用dplyr函数

函数中的主要dplyr函数将参数 传递给dplyr函数

dplyr:过滤data.frame中两列相等的过滤器

已采取措施解决这些问题.有一个小插图来概述基本修复.然而,在我的拙见中,小插图缺乏对函数式编程的解释.没有一个函数作为示例编写.它也没有解决通常出现的任何混淆的例子.希望随着修复NSE的呼声的增加,我们最终可能得到足够的响应.

作为非标准评估在编程中可能导致的混乱的最后一个例子,我试图为这个用户的解决方案工作一段时间无济于事.它只是要求以summarise编程方式使用:

使用dplyr分组功能的子功能