0

我喜欢用字符输入创建 dplyr 函数,所以会很高兴看到新的 v0.6.0 即将推出。

为了好玩和学习当前 dplyr 版本 0.5.0.9004,我尝试制作一个灵活的函数,它可以接受字符参数和表达式(NSE)。

我确实成功了,但这不能做得更优雅吗?!

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)
4

1 回答 1

2

character由于 OP 的函数在某些情况下将字符串作为输出,因此尚不清楚预期的输出

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

在这里,我们假设函数应该评估以获得列'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

还有一些案例

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
于 2017-04-30T05:24:37.787 回答