我有一个例程来创建一些图ggplot:
getPlotList = function(param.list, data=db, y, color){
param.list %>% sapply(function(var){
ggplot(data=data, aes(x=data[[var]], y=data[[y]], color=data[[color]]))+
stat_summary(fun.y = mean, fun.ymin = function(x){mean(x) - sem(x)}, fun.ymax = function(x){mean(x) + sem(x)}, geom = "errorbar", width=.1, position = position_dodge(0.3), na.rm = TRUE) +
stat_summary(fun.y = mean, geom = "point", position = position_dodge(0.3), na.rm = TRUE) +
ylim(0, NA) +
}, simplify = FALSE, USE.NAMES = TRUE)
}
Run Code Online (Sandbox Code Playgroud)
我用的是这样的:
c("col1", "col2", "col3") %>% getPlotList(y="col4", color="col5")
Run Code Online (Sandbox Code Playgroud)
这完美地工作(我有几十个绘图),并给出这样的结果(但没有n = ...标签):

问题是,我的计数对于每种颜色都是相同的,但它可以随x变化.
由于存在错误栏(如果n = 1或n = 0则不会显示),我必须在标签中显示计数,就像我在图片上所做的那样(使用Paint).
在SO上有很多类似的问题(比如这个,这个,这个,等等......),但是所有使用geom_hist或geom_bar碰巧都有..count..可用的元变量,不像stat_summary我正在使用的那样.
我怎么能添加这些标签?
PS:我试图在我的函数中使用quosures而不是data [[...]]但是失败了.这不是问题的主要部分,但如果有人有这个想法,这对我很有帮助.
这是使用这些示例数据构建的:
sampleData <-
data.frame(
col1 = factor(rep(LETTERS[1:4], c(12, 6, 16, 20)*5)
, levels = LETTERS[1:4])
, col2 = factor(rep(LETTERS[1:4], c(1, 17, 16, 20)*5)
, levels = LETTERS[1:4])
, col3 = factor(rep(LETTERS[1:4], c(0, 18, 16, 20)*5)
, levels = LETTERS[1:4])
, col4 = rnorm(54*5, 4, 2)
, col5 = factor(rep(1:5, 54))
)
Run Code Online (Sandbox Code Playgroud)
基本方法是手动添加标签.为此,我曾经table计算每个X /颜色的出现次数并生成一个新的data.frame来显示它们.请注意,虽然您说 X分组中的每种颜色始终具有相同的样本大小,但最好是进行防御性编程.我不是信任它(例如,使用第一种颜色的计数),而是apply用来获取所有唯一值.只要只有一个,效果是一样的.但是,如果有多个,这将给你一个指示.
此外,我继续并将映射切换为使用,aes_string以便它将填充您的列标签.如果您不喜欢这种行为,只需覆盖ylab等.
类似地,sem找不到该函数(我假设它是一个自定义函数),所以我使用了该mean_cl_normal函数,这具有利用fun.data参数更清晰代码的额外优势.(我也更喜欢显示SEM的置信区间,但这比实质更具风格).
getPlotList = function(param.list, data=db, y, color){
param.list %>% sapply(function(var){
myCounts <- table(data[[var]], data[[color]])
forLabels <-
data.frame(
x = row.names(myCounts)
, label = paste("n =", apply(myCounts, 1, function(x){paste(unique(x), collapse = ";")}))
, y = 0.5
)
ggplot(data=data, aes_string(x=var, y=y, color=color))+
stat_summary(fun.data = mean_cl_normal, position = position_dodge(0.3), na.rm = TRUE) +
stat_summary(fun.y = mean, geom = "point", position = position_dodge(0.3), na.rm = TRUE) +
ylim(0, NA) +
geom_text(aes(x = x, y = y, label = label, color = NA)
, forLabels
, show.legend = FALSE)
}, simplify = FALSE, USE.NAMES = TRUE)
}
Run Code Online (Sandbox Code Playgroud)
现在,这段代码:
c("col1", "col2", "col3") %>% getPlotList(y="col4", color="col5", data = sampleData)
Run Code Online (Sandbox Code Playgroud)
给出以下图表:
应@Nettle的要求,我修改了代码以使用更多的代码tidyverse,特别是使用标准评估来循环列列表,而不是使用table之前的基本方法.我相信代码应该具有相同的功能.主要优点是删除中间变量,但有人可能认为那些提高了可读性.
getPlotList <- function(param.list, data=db, y, color){
param.list %>% sapply(function(var){
ggplot(data=data, aes_string(x=var, y=y, color=color))+
stat_summary(fun.data = mean_cl_normal, position = position_dodge(0.3), na.rm = TRUE) +
stat_summary(fun.y = mean, geom = "point", position = position_dodge(0.3), na.rm = TRUE) +
ylim(0, NA) +
geom_text(aes_string(x = var, y = "y", label = "label", color = NA)
, data %>%
count(!!as.name(var), !!as.name(color)) %>%
group_by(!!as.name(var)) %>%
summarise(
label = paste("n =", paste(unique(n), collapse = ";"))
) %>%
mutate(y = 0.5)
, show.legend = FALSE)
}, simplify = FALSE, USE.NAMES = TRUE)
}
Run Code Online (Sandbox Code Playgroud)