0

I like creating dplyr functions with character inputs, so will be very happy with new v0.6.0 coming up.

For fun and learning current dplyr version 0.5.0.9004, i tried to make a flexible function that can take a character argument as well as an expressions (NSE).

I did succeed, but can't this be done more elegantly?!

d = data.frame(v1=1:2, v2=9:8)

fixquo <- function(x){
  # 'fixquo' expects a enquo-ed object, then sees if enquo-ing needs to be 'reversed'...
  if(!length(tryCatch({ls(get_env(x))}, error=function(e) "empty"))) 
    x = as.name(as.character(UQ(x))[2])
    x
 }

Dtest <- function(d, x="v1", res="z"){
  x <- enquo(x) %>% fixquo()
  d %>% mutate(!!res := UQ(x))
}
Dtest(d)
Dtest(d, "v1")
Dtest(d, v1)
Dtest(d, v2)

1 Answers1

2

It is not clear about the expected output as the OP's function gives the character string as output for some cases

Dtest(d, "v1")
#   v1 v2  z
#1  1  9 v1
#2  2  8 v1
#Warning message:
#In ls(get_env(x)) : ‘get_env(x)’ converted to character string

Here, we assume that the function should evaluate to get the value of the column 'v1'

DtestN <- function(dat, x, res = "z"){
          lst <- as.list(match.call())
          x <- if(is.character(lst$x)) {
                  rlang::parse_quosure(x, env = parent.frame())
                  } else enquo(x)
          res <- if(!is.character(lst$res)) quo_name(enquo(res)) else res
          dat %>%
             mutate(UQ(res) := UQ(x)) 


 }


DtestN(d, 'v1')
#  v1 v2 z
#1  1  9 1
#2  2  8 2

DtestN(d, v1)
#  v1 v2 z
#1  1  9 1
#2  2  8 2

DtestN(d, v1, z)
#  v1 v2 z
#1  1  9 1
#2  2  8 2

DtestN(d, 'v1', z)
#  v1 v2 z
#1  1  9 1
#2  2  8 2

Some more cases

DtestN(d, v1, new)
#  v1 v2 new
#1  1  9   1
#2  2  8   2 
DtestN(d, v1, 'new')
#   v1 v2 new
#1  1  9   1
#2  2  8   2


DtestN(d, v2, 'new')
#  v1 v2 new
#1  1  9   9
#2  2  8   8
akrun
  • 874,273
  • 37
  • 540
  • 662
  • I forgot to mention that both libraries dplyr and rlang were laoded and attached, with library(dplyr) and library(rlang). I should have used rlang:: before the get_env() and the UQ() functions. – Hans Schepers Apr 30 '17 at 13:38
  • @HansSchepers Ok, no problem. I just used `rlang` because i didn't attach it – akrun Apr 30 '17 at 13:39
  • dplyr apparently makes rlang to be added to the loaded Namespaces, but not to the search() list. Strange to me is that user-typed UQ() can be used within the mutate() function, even when rlang is not on the search list. using UQ() yourself (e.g. in defining a function like fixquo() above) is an error without the rlang:: ! – Hans Schepers Apr 30 '17 at 14:08
  • @HansSchepers I think it is still under development. Probably gets fixed before the new release – akrun Apr 30 '17 at 14:10
  • What is also surprising, is that DtestN(d) , so without specifying the argument x, works even though there is no default in the function definition!? Also a new effect of enquo-ing..! The mutate() does not care and defines the result column 'z' just as a NULL, so the original d comes out. – Hans Schepers Apr 30 '17 at 14:29