R懒惰评估ifelse逻辑条件

时间:2017-04-10 13:47:09

标签: r dplyr lazyeval

我有以下data.table

dtable <- data.table(column1 = c(1, 2, 3, 5, 6, 7, 8),
                     column2 = c(1, 1, 1, 5, 5, 6, 8),
                     column3 = c(7, 8, 9, 0, 9, 2, 3))

我想制作类似以下功能的东西,但是在参数化函数中:

dtable %>% 
  dplyr::group_by(column1) %>% 
  dplyr::summarise(Result = ifelse(column1 == column2, "A", "B"))

为此,我创建了以下功能:

Test <- function(.df, .columnName, .columnToGroup){
  res <- .df %>%
    # This line is interpreted correctly
    dplyr::group_by_(lazyeval::interp(.columnToGroup, .columnToGroup = as.name(.columnToGroup))) %>%

    # This line does not interpret the == condition as a logical one
    dplyr::summarise_(Result = ifelse((lazyeval::interp(.columnToGroup == .columnName,
                                                        .columnToGroup = as.name(.columnToGroup),
                                                        .columnName = as.name(.columnName))),
                                      "A", "B"))
  return(res)
}

我将非标准评估函数(group_by_summarise_)与lazyeval::interp函数结合使用,但==条件未被解释正确的方式,我得到以下的例外:

Test(dtable, "column1", "column2")

 Error in UseMethod("interp") : 
  no applicable method for 'interp' applied to an object of class "logical"

我尝试了许多不同的组合(quoteexpr_envas.lazy等等,但没有运气。感谢这个伟大的Non-standard evaluation guide我之前能够使用这些lazyeval函数来评估算术表达式,但是我无法找到使它们解释这段代码中的逻辑条件的方法

非常感谢任何帮助。

1 个答案:

答案 0 :(得分:1)

使用ifelse,我们可以尝试(在评论中使用@docendodiscimus使用list

Test <- function(.df, .columnName, .columnToGroup){
 .df %>%   
   dplyr::group_by_(.dots = .columnToGroup )%>%
            dplyr::summarise_(.dots =

                            setNames(list(lazyeval::interp(quote(ifelse(colGrp == colName,
                               "A", "B")), .values = list(colGrp = as.name(.columnToGroup),
                                                    colName = as.name(.columnName)))),
                                  "Result"))

 }

res2 <- Test(dtable, "column2", "column1")
identical(res1, res2)
#[1] TRUE

其中&#39; res1&#39;是

res1 <- dtable %>% 
          dplyr::group_by(column1) %>% 
          dplyr::summarise(Result = ifelse(column1 == column2, "A", "B"))

更新

新版dplyr0.6.0(等待2017年4月发布),我们也可以在group_bysummarise内取消引用。 enquo函数与substitute的{​​{1}}类似,通过占用输入参数可以创建base R并且不加引号(quosure或{{1}在} !!UQ内进行评估

group_by