2017-04-14 41 views
8
library(dplyr) #Devel version, soon-to-be-released 0.6.0 
library(tidyr) 
library(ggplot2) 
library(forcats) #for gss_cat data 

我试图写一个从即将要发布的dplyr devel的版本tidyr组合在一起quosures功能使用开发人员版本dplyr的enquo和quo_name的一个功能:: gather和ggplot2。到目前为止,它似乎与tidyr一起工作,但我在绘图时遇到了麻烦。如何使用tidyr和GGPLOT2

下面的功能似乎与tidyr的收集工作:

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

但我不能想出如何使该地块的工作。我尝试用ggplot2使用!! gath,但它不起作用。

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)) 
} 
+0

我要回答的更近的问题适用于:使用dplyr SE与GGPLOT2(https://stackoverflow.com/questions/45279287/use-dplyr-se-with-ggplot2/47044567#47044567)。简而言之,我建议你使用aes_(x =〜value,y =〜perc,fill = gath)。当你已经有quards在使用时,语法比使用aes_string更清晰。 – Stanwood

回答

6

我觉得主要的问题是ggplot是贪婪的时候,它会评估!!gath和做!(!gath),抛出一个错误not(gath)已经没有意义。当我尝试使用!!时,我遇到了这个问题,所以我对使用它的糖形式感到厌倦。

如果有人更精确地可以正确识别问题,它肯定会有帮助。

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

您在问题中编写的函数调用似乎存在一些错误。适当的间隔你的代码将有助于避免这一点

你也没有使用rlang电话,我只是没有安装最新的dplyr版本。

编辑使用更简单mtcars例如一些想法:

TBH我不是很确定什么是怎么回事,但我想这是与事实ggplot2现在是比较老的做,有一个稍微不同的设计?走进aesdebug,我们发现类似的结构,以

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,那么审美可以被映射为正常。

我想dplyr动词没有这个额外的映射步骤,其中的参数被以相同的方式操纵到一些中间结构中,所以我们没有这个问题。

此外,当我说你不必使用rlang调用,这是因为我认为这个功能被重新导出到新的dplyr版本。由于前面提到的整个!!(...)!(!(...)),我更喜欢使用rlang::"!!"rlang::UQE(我相信这完全等价)。

大部分是猜测,如果有人能纠正我的任何错误,我将不胜感激。

+0

谢谢你的答案。所以当你说我不需要使用rlang调用时,我仍然使用 - fill = eval('!!'(gath))))?你能详细阐述一下吗?另外,“eval”是做什么的?我对SE和NSE仍然很陌生,所以任何额外的细节将不胜感激! – Mike

+0

添加了一个编辑,让我们猜测为什么NSE在此处无法正常工作。上面的一些东西似乎违反了NSE小插曲中概述的惯例:http://dplyr.tidyverse.org/articles/programming.html,因此我觉得'ggplot'可能略微超出了本文的范围,到它的年龄 –

8

为了使这项工作,我不得不使用dplyr::quo_name改变平静成一个字符串。我还必须使用ggplot2::aes_string,这也需要所有的输入为字符串,因此引用""

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

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

有什么办法可以避免使用ggplot2 :: aes_string? – Mike

+1

我认为这是比接受的答案更好的解决方案 – Andrie

+0

@Andrie我同意。我发布后,OP的评论如何做到这一点W/o aes_string –

0

我最近在别处回答了这个问题(Use dplyr SE with ggplot2)。不知道如何标记重复,所以我会在这里重复。

如果您已经办理quosures语法是清洁,如果你使用 aes_,而不是aes_string

这段代码应该在你的例子中工作。请注意,所有硬编码变量(value,perc,key)都是在用户直接使用静态(gath)时用tilda引用的。

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