Mudando a definição do whisker no geom_boxplot

Eu estou tentando usar ggplot2 / geom_boxplot para produzir um boxplot onde os bigodes são definidos como o percentil 5 e 95 em vez de 0,25-1,5 IQR / 0,75 + IQR e outliers desses novos bigodes são plotados como de costume. Eu posso ver que a estética do geom_boxplot inclui ymax / ymin, mas não está claro para mim como eu coloco valores aqui. Parece que:

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

deve ser capaz de ajudar, mas eu não sei como relacionar os resultados deste stat para definir a estética geom_boxplot () apropriada:

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

Eu vi outros posts onde as pessoas mencionam essencialmente a construção de um object parecido com boxplot manualmente, mas eu prefiro manter intacta a gestalt do boxplot, apenas revisando o significado de duas variables ​​sendo desenhadas.

geom_boxplot com stat_summary pode fazer isso:

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

Com base na resposta do @konvas, começando em ggplot2.0.x , você pode estender o ggplot usando o sistema ggproto e definir sua própria estatística.

Copiando o código ggplot2 stat_boxplot e fazendo algumas edições, você pode definir rapidamente um novo stat ( stat_boxplot_custom ) que usa os percentis que deseja usar como argumento ( qs ) em vez do argumento coef usado pelo stat_boxplot . A nova estatística é definida aqui:

 # 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, ... ) ) } 

Então, a function da camada é definida. Note que b / c eu copiei diretamente do stat_boxplot , você tem que acessar algumas funções internas do ggplot2 usando ::: . Isso inclui muitas coisas copiadas diretamente do StatBoxplot , mas a área chave está no cálculo das statistics diretamente do argumento qs : stats <- as.numeric(stats::quantile(data$y, qs)) dentro do compute_group function.

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

Há também uma essência aqui , contendo este código.

Então, stat_boxplot_custom pode ser chamado assim como 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)) 

Exemplo que se estende até 5 / 95th

Agora é possível especificar os pontos finais dos bigodes em ggplot2_2.1.0 . Copiando dos exemplos em ?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" ) 

insira a descrição da imagem aqui

Intereting Posts