关于如何用样本大小标记箱形图,有很多解释,包括this good one。所有这些似乎都使用max(x)
或median(x)
来定位样本大小。
我想知道是否有方法可以轻松地将标签放置在绘图的顶部或底部,尤其是在facet中使用scale = "free_y"
命令时,轴的最大值和最小值是通过ggplot自动为每个方面选取。
原因是我创建了多个方面,其中分布很窄,方面很小。如果它位于图的顶部或底部,那么读取样本大小会更容易......但是我想使用" free_y"因为在某些方面存在有意义的差异,这些方面被数据中具有更大跨度的方面所模糊。
使用链接帖子中稍加修改的示例:
# function for number of observations
give.n <- function(x){
return(c(y = median(x)*1.05, label = length(x)))
# experiment with the multiplier to find the perfect position
}
# function for mean labels
mean.n <- function(x){
return(c(y = median(x)*0.97, label = round(mean(x),2)))
# experiment with the multiplier to find the perfect position
}
# plot
ggplot(mtcars, aes(factor(cyl), mpg, label=rownames(mtcars))) +
geom_boxplot(fill = "grey80", colour = "#3366FF") +
stat_summary(fun.data = give.n, geom = "text", fun.y = median) +
stat_summary(fun.data = mean.n, geom = "text", fun.y = mean, colour = "red") +
facet_grid(cyl~., scale="free_y")
鉴于此设置,我如何找到每个面的x轴的最小值或最大值,并将样本大小放在那里而不是每个盒子的中间值,最小值或最大值?
修改
我用以下R.S。答案的信息更新问题。目前还没有回答,但是他们的建议提供了在何处查找此信息的解决方案。
ggplot_build(gg)$layout$panel_ranges[[order(levels(factor(mtcars$cyl)))[1]]]$y.range[1]
给出mtcars $ cyl的第一个因子的y范围的最小值。因此,根据我的逻辑,我们需要在没有stat_summary
语句的情况下构建绘图,然后使用give.n
函数找到样本大小和最小y范围。之后,我们可以将stat_summary
语句添加到情节中......如下所示:
# plot
gg = ggplot(mtcars, aes(factor(cyl), mpg, label=rownames(mtcars))) +
geom_boxplot(fill = "grey80", colour = "#3366FF") +
facet_grid(cyl~., scale="free_y")
# function for number of observations
give.n <- function(x){
return(c(y = ggplot_build(gg)$layout$panel_ranges[[order(levels(factor(mtcars$cyl)))[x]]]$y.range[1], label = length(x)))
# experiment with the multiplier to find the perfect position
}
gg +
stat_summary(fun.data = give.n, geom = "text", fun.y = "median")
但是......上面的代码不起作用,因为我不太了解give.n
函数迭代的内容。用1:3中的任何一个替换[[x]]
将该方面的所有样本大小绘制为最小值,这样就是进步。
以下是使用[[2]]
的图,因此所有样本大小都绘制在17.62,即第二个方面范围的最小值。
答案 0 :(得分:1)
您可以使用ggplot_build
检查ggplot对象的结构,特别是x和y面板范围存储在布局中。将绘图分配给对象并查看结构:
gg <- ggplot(mtcars, aes(factor(cyl), mpg, label=rownames(mtcars))) +
geom_boxplot(fill = "grey80", colour = "#3366FF") +
stat_summary(fun.data = give.n, geom = "text", fun.y = median) +
stat_summary(fun.data = mean.n, geom = "text", fun.y = mean, colour = "red") +
facet_grid(cyl~., scale="free_y")
ggplot_build(gg)
特别感兴趣的是:
ggplot_build(gg)$layout$panel_ranges
3个面板的ylim以c(ymin,ymax)给出并存储在:
下 ggplot_build(gg)$layout$panel_ranges[[1]]$y.range
ggplot_build(gg)$layout$panel_ranges[[2]]$y.range
ggplot_build(gg)$layout$panel_ranges[[3]]$y.range
编辑回复评论以及如何将此布局信息纳入情节。在这里,我们使用dplyr分别计算cyl
分组的统计摘要,并创建单独的数据框以合并到ggplot2中,而不是使用stat_summary
。
library(dplyr)
gg.summary <- group_by(mtcars, cyl) %>% summarise(mean=mean(mpg), median=median(mpg), length=length(mpg))
解析ylim范围并包含到统计摘要df中,统计摘要df按cyl分组,这是我们面临的变量:
gg.summary$panel.ylim <- sapply(order(levels(factor(mtcars$cyl))), function(x) ggplot_build(gg)$layout$panel_ranges[[x]]$y.range[1])
# # A tibble: 3 x 5
# cyl mean median length panel.ylim
# <dbl> <dbl> <dbl> <int> <dbl>
# 1 4 26.66364 26.0 11 20.775
# 2 6 19.74286 19.7 7 17.620
# 3 8 15.10000 15.2 14 9.960
在ggplot中使用,我相信这是你想要的情节:
gg + geom_text(data=gg.summary, (aes(x=factor(cyl), y=panel.ylim, label=paste("n =",length)))) +
geom_text(data=gg.summary, (aes(x=factor(cyl), y=median*0.97, label=format(median, nsmall=2))))