I have the following 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))
I would like to make something like the following functionality, but in a parametrized function:
dtable %>%
dplyr::group_by(column1) %>%
dplyr::summarise(Result = ifelse(column1 == column2, "A", "B"))
To do this, I've created the following function:
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)
}
I'm using the Non-Standard Evaluation functions (group_by_
and summarise_
) in combination with the lazyeval::interp
function, but the ==
condition is not interpreted the right way, and I get the following exeception:
Test(dtable, "column1", "column2")
Error in UseMethod("interp") :
no applicable method for 'interp' applied to an object of class "logical"
I've tried many different combinations (quote
, expr_env
, as.lazy
, etc.) with no luck. Thanks to this great Non-standard evaluation guide I was able to use these lazyeval
functions to evaluate arithmetic expressions before, but I can't find the way to make them to interpret a logical condition in this piece of code.
Any help would be greatly appreciated.
With ifelse
, we can try (using @docendodiscimus use of list
in comments)
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
where 'res1' is
res1 <- dtable %>%
dplyr::group_by(column1) %>%
dplyr::summarise(Result = ifelse(column1 == column2, "A", "B"))
With the new version of dplyr
i.e. 0.6.0
(awaiting release on April 2017), we can also unquote within group_by
and summarise
. The enquo
function does similar job as substitute
from base R
by taking up the input argument can creating a quosure
and this gets unquoted (!!
or UQ
) within group_by
and summarise
for evaluation
Test1 <- function(df, colN, colGrp){
colN <- enquo(colN)
colGrp <- enquo(colGrp)
df %>%
group_by(!!colGrp) %>%
summarise(Result = if_else((!!colGrp) == (!!colN), "A", "B"))
}
res3 <- Test1(dtable, column2, column1)
identical(res2, res3)
#[1] TRUE