在geom_boxplot中更改胡须定义

我试图用ggplot2 / geom_boxplot来产生一个boxplot,其中晶须被定义为第5和第95百分位数,而不是0.25 – 1.5 IQR / 0.75 + IQR,并且像往常一样绘制这些新晶须的exception值。 我可以看到,geom_boxplot美学包括ymax / ymin,但我不清楚我是如何把价值在这里。 这好像是:

stat_quantile(quantiles = c(0.05, 0.25, 0.5, 0.75, 0.95)) 

应该能够提供帮助,但是我不知道如何将这个统计的结果关联起来以设置合适的geom_boxplot()美学:

 geom_boxplot(aes(ymin, lower, middle, upper, ymax)) 

我曾经看过其他的post,其中提到的人物本质上是手工build造一个类似箱子的物体,但是我宁愿保留整个箱体的形态,只是修改其中两个variables的含义。

geom_boxplot与stat_summary可以做到这一点:

 # define the summary function f <- function(x) { r <- quantile(x, probs = c(0.05, 0.25, 0.5, 0.75, 0.95)) names(r) <- c("ymin", "lower", "middle", "upper", "ymax") r } # sample data d <- data.frame(x=gl(2,50), y=rnorm(100)) # do it ggplot(d, aes(x, y)) + stat_summary(fun.data = f, geom="boxplot") # example with outliers # define outlier as you want o <- function(x) { subset(x, x < quantile(x)[2] | quantile(x)[4] < x) } # do it ggplot(d, aes(x, y)) + stat_summary(fun.data=f, geom="boxplot") + stat_summary(fun.y = o, geom="point") 

基于@ konvas的答案,从ggplot2.0.x开始,您可以使用ggproto系统扩展ggplot并定义自己的属性。

通过复制ggplot2 stat_boxplot代码并进行一些编辑,您可以快速定义一个新的stat( stat_boxplot_custom ),它将您想要使用的百分位数作为参数( qs ),而不是stat_boxplot使用的coef参数。 新的统计在这里定义:

 # modified from https://github.com/tidyverse/ggplot2/blob/master/R/stat-boxplot.r library(ggplot2) stat_boxplot_custom <- function(mapping = NULL, data = NULL, geom = "boxplot", position = "dodge", ..., qs = c(.05, .25, 0.5, 0.75, 0.95), na.rm = FALSE, show.legend = NA, inherit.aes = TRUE) { layer( data = data, mapping = mapping, stat = StatBoxplotCustom, geom = geom, position = position, show.legend = show.legend, inherit.aes = inherit.aes, params = list( na.rm = na.rm, qs = qs, ... ) ) } 

然后,定义图层function。 请注意,我直接从stat_boxplot复制的B / C,你必须使用:::访问一些内部的ggplot2函数。 这包括很多从StatBoxplot直接复制的东西,但是关键区域是直接从qs参数计算stats: stats <- as.numeric(stats::quantile(data$y, qs))compute_groupfunction。

 StatBoxplotCustom <- ggproto("StatBoxplotCustom", Stat, required_aes = c("x", "y"), non_missing_aes = "weight", setup_params = function(data, params) { params$width <- ggplot2:::"%||%"( params$width, (resolution(data$x) * 0.75) ) if (is.double(data$x) && !ggplot2:::has_groups(data) && any(data$x != data$x[1L])) { warning( "Continuous x aesthetic -- did you forget aes(group=...)?", call. = FALSE ) } params }, compute_group = function(data, scales, width = NULL, na.rm = FALSE, qs = c(.05, .25, 0.5, 0.75, 0.95)) { if (!is.null(data$weight)) { mod <- quantreg::rq(y ~ 1, weights = weight, data = data, tau = qs) stats <- as.numeric(stats::coef(mod)) } else { stats <- as.numeric(stats::quantile(data$y, qs)) } names(stats) <- c("ymin", "lower", "middle", "upper", "ymax") iqr <- diff(stats[c(2, 4)]) outliers <- (data$y < stats[1]) | (data$y > stats[5]) if (length(unique(data$x)) > 1) width <- diff(range(data$x)) * 0.9 df <- as.data.frame(as.list(stats)) df$outliers <- list(data$y[outliers]) if (is.null(data$weight)) { n <- sum(!is.na(data$y)) } else { # Sum up weights for non-NA positions of y and weight n <- sum(data$weight[!is.na(data$y) & !is.na(data$weight)]) } df$notchupper <- df$middle + 1.58 * iqr / sqrt(n) df$notchlower <- df$middle - 1.58 * iqr / sqrt(n) df$x <- if (is.factor(data$x)) data$x[1] else mean(range(data$x)) df$width <- width df$relvarwidth <- sqrt(n) df } ) 

这里也有一个要点 ,包含这个代码。

然后,可以像stat_boxplot一样stat_boxplot

 library(ggplot2) y <- rnorm(100) df <- data.frame(x = 1, y = y) # whiskers extend to 5/95th percentiles by default ggplot(df, aes(x = x, y = y)) + stat_boxplot_custom() # or extend the whiskers to min/max ggplot(df, aes(x = x, y = y)) + stat_boxplot_custom(qs = c(0, 0.25, 0.5, 0.75, 1)) 

例子延伸到5 / 95th

现在可以在ggplot2_2.1.0指定胡须端点。 从?geom_boxplot的例子复制:

  # It's possible to draw a boxplot with your own computations if you # use stat = "identity": y <- rnorm(100) df <- data.frame( x = 1, y0 = min(y), y25 = quantile(y, 0.25), y50 = median(y), y75 = quantile(y, 0.75), y100 = max(y) ) ggplot(df, aes(x)) + geom_boxplot( aes(ymin = y0, lower = y25, middle = y50, upper = y75, ymax = y100), stat = "identity" ) 

在这里输入图像描述