如何在带有tidyr和ggplot2的函数中使用dplyr的enquo和quo_name [英] How to use dplyr's enquo and quo_name in a function with tidyr and ggplot2

查看:180
本文介绍了如何在带有tidyr和ggplot2的函数中使用dplyr的enquo和quo_name的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

library(dplyr) #Devel version, soon-to-be-released 0.6.0
library(tidyr)
library(ggplot2)
library(forcats) #for gss_cat data

我正在尝试编写一个函数,该函数将即将发布的dplyr devel版本与tidyr::gatherggplot2结合在一起.到目前为止,它似乎可以与tidyr一起使用,但是我在绘制时遇到了麻烦.

I'm attempting to write a function that combines quosures from the soon-to-be-released dplyr devel version together with tidyr::gather and ggplot2. So far it seems to work with tidyr, but I'm having trouble with the plotting.

以下功能似乎可以与tidyr's gather一起使用:

The below function seems to work with tidyr's gather:

GatherFun<-function(gath){
  gath<-enquo(gath)

  gss_cat%>%select(relig,marital,race,partyid)%>%
    gather(key,value,-!!gath)%>%
    count(!!gath,key,value)%>%
    mutate(perc=n/sum(n))
}

但是我不知道如何使这些图起作用.我尝试将!!gathggplot2结合使用,但是没有用.

But I can't figure out how to make the plots work. I tried using !!gath with ggplot2, but it didn't work.

GatherFun<-function(gath){
  gath<-enquo(gath)

  gss_cat%>%select(relig,marital,race,partyid)%>%
    gather(key,value,-!!gath)%>%
    count(!!gath,key,value)%>%
    mutate(perc=n/sum(n))%>%
    ggplot(aes(x=value,y=perc,fill=!!gath))+
       geom_col()+
       facet_wrap(~key, scales = "free") +
       geom_text(aes(x = "value", y = "perc", 
                     label = "perc", group = !!gath),
                 position = position_stack(vjust = .05))
}

推荐答案

我觉得主要问题是ggplot在尝试评估!!gath并执行!(!gath)时过于贪婪,并抛出错误为not(gath)没有任何意义.当我尝试使用!!时,我遇到了很多问题,所以我有点厌倦以糖的形式使用它.

I feel like the main problem is ggplot is greedy when it tries to evaluate !!gath and does !(!gath), throwing an error as not(gath) has no meaning. I've has this issue crop up a lot when I've tried to use !! so I'm kinda weary about using it in its sugar form.

如果更精确的人能够正确识别问题,那肯定会有所帮助.

If someone more precise could correctly identify the problem it would definitely be helpful.

gather_func = function(gath) {

  gath = enquo(gath)

  gss_cat %>%
    select(relig, marital, race, partyid) %>%
    gather(key, value, -!!gath) %>%
    count(!!gath, key, value) %>%
    mutate(perc = round(n/sum(n), 2)) %>%
    ggplot(aes(x = value, y = perc, fill = eval(rlang::`!!`(gath)))) +
    geom_col() + 
    facet_wrap(~key, scales = "free") +
    geom_text(
      aes(
        x = value, 
        y = perc, 
        label = perc, 
        group = eval(rlang::`!!`(gath))
      ),
      position = position_stack(vjust = .05)
    )
}

您在问题中编写的函数调用中似乎存在一些错误.正确地间隔代码可以避免这种情况.

There seems to be a few mistakes in the function call you wrote in the question. properly spacing your code will help avoid that.

您也没有使用rlang呼叫,我只是没有安装最新的dplyr版本.

You also don't have you use the rlang call, I just don't have the newest dplyr version installed.

编辑,使用更简单的mtcars示例进行一些思考:

EDIT Some thoughts using a simpler mtcars example:

我不太确定这是怎么回事,但我想这与ggplot2现在相对较旧并且设计略有不同的事实有关吗?用debug进入aes,我们发现类似于

Tbh I'm quite unsure of what's going on here, but I imagine it's to do with the fact the ggplot2 is relatively old now and has a slightly different design? Stepping into aes with debug, we find a structure similar to

structure(list(x = mpg, y = eval(rlang::UQE(var))), .Names = c("x", 
"y"), class = "uneval")

(这不会遍历解释器,但大致与结构类似).我认为这表明了为什么在这里需要eval调用的原因,o/w ggplot试图将rlang::UQE(var)映射到y美学并且报告它不知道该如何处理类name. eval将名称评估为cyl,则可以将外观映射为正常.

(This won't run through the interpreter but is roughly what the structure looks like). I think this shows why the eval call is necessary here, o/w ggplot is trying to map rlang::UQE(var) to the y aesthetic and reports it doesn't know what to do with something of class name. eval evaluates the name to, say, cyl, then the aesthetic can be mapped as normal.

我想象dplyr动词没有这个额外的映射步骤,在该步骤中,参数以相同的方式被操纵到某种中间结构中,因此我们没有这个问题.

I imagine dplyr verbs don't have this extra mapping step where the arguments are manipulated into some intermediate structure in the same way, so we don't have this issue.

另外,当我说您不必使用rlang调用时,这是因为我假设此函数已重新导出到新的dplyr版本中.由于我前面提到的整个!!(...)!(!(...))内容,我更喜欢使用rlang::"!!"rlang::UQE(我认为它们完全等效).

Also, when I said you don't have to use the rlang call, it was because I assumed this function was re-exported into the new dplyr version. Because of the whole !!(...) or !(!(...)) thing I mentioned earlier, I prefer to use rlang::"!!", or rlang::UQE (which are exactly equivalent I believe).

不过,其中大多数是猜测,如果有人可以纠正我犯错的任何内容,将不胜感激.

Most of this is speculation though and if someone could correct me on anything I've got wrong it would be appreciated.

这篇关于如何在带有tidyr和ggplot2的函数中使用dplyr的enquo和quo_name的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆