library(dplyr) #Devel version, soon-to-be-released 0.6.0
library(tidyr)
library(ggplot2)
library(forcats) #for gss_cat data
我正在尝试编写一个功能,该功能将即将发布的dplyr
devel版本的排序与tidyr::gather
和ggplot2
结合起来。到目前为止它似乎与tidyr
一起使用,但我在绘图方面遇到了麻烦。
以下功能似乎适用于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))
}
但我无法弄清楚如何让这些情节发挥作用。我尝试将!!gath
与ggplot2
一起使用,但它没有用。
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 :(得分:11)
为了完成这项工作,我必须使用dplyr::quo_name
将quosure更改为字符串。我还必须使用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 :(得分:8)
我觉得主要问题是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
现在相对陈旧并且设计略有不同的事实有关?使用aes
进入debug
,我们找到类似于
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
(我认为这完全相同)。
这大部分都是猜测,如果有人能纠正我的任何错误,我将不胜感激。
答案 2 :(得分:2)
现在可以在ggplot2 v3.0.0
的aes
内使用整洁的评估。因此不再需要aes_string
。
# install.packages("ggplot2", dependencies = TRUE)
library(tidyverse)
GatherFun2 <- 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() +
geom_col(aes(x = value, y = perc, fill = !! gath)) +
facet_wrap(~ key, scales = "free") +
xlab(NULL) +
geom_text(aes(x = value, y = perc,
label = ifelse(perc == 0, "", perc),
group = !! gath),
position = position_stack(vjust = .2)) +
theme(legend.position = "bottom",
axis.text.x = element_text(angle = 90, hjust = 1.0))
}
GatherFun2(marital)
答案 3 :(得分:0)
我最近在其他地方回答了这个问题(Use dplyr SE with ggplot2)。不知道如何标记重复,所以我将在此重复。
如果您已经在处理quosures,则使用时语法更清晰
aes_
而不是aes_string
。
这段代码应该适用于您的示例。请注意,所有硬编码变量(value,perc,key)都是用tilda引用的,而quosure(gath)是直接使用的。
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))