Mengubah definisi kumis di geom_boxplot

Saya mencoba menggunakan ggplot2 / geom_boxplot untuk menghasilkan plot kotak di mana kumis didefinisikan sebagai persentil ke-5 dan ke-95, bukan 0,25 - 1,5 IQR / 0,75 + IQR dan outlier dari kumis baru tersebut diplot seperti biasa. Saya dapat melihat bahwa estetika geom_boxplot menyertakan ymax/ymin, tetapi tidak jelas bagi saya bagaimana saya memberi nilai di sini. Sepertinya:

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

seharusnya bisa membantu, tapi saya tidak tahu bagaimana menghubungkan hasil stat ini dengan mengatur estetika geom_boxplot() yang sesuai:

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

Saya telah melihat posting lain di mana orang-orang menyebutkan pada dasarnya membangun objek seperti plot kotak secara manual, tapi saya lebih suka membiarkan seluruh gestalt plot kotak tetap utuh, hanya merevisi arti dari dua variabel yang digambar.


person cswingle    schedule 22.01.2011    source sumber


Jawaban (3)


geom_boxplot dengan stat_summary dapat melakukannya:

# 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")
person kohske    schedule 22.01.2011
comment
kohske, itu memang mengubah kumisnya (terima kasih!), tapi outliernya hilang. - person cswingle; 22.01.2011
comment
contoh telah diperbarui: ada berbagai cara untuk melakukannya, tapi mungkin ini cara termudah untuk memplot outlier di geom_point. - person kohske; 22.01.2011
comment
Besar! Fungsi o mungkin harus menggunakan probs = c(0.05, 0.95)[1] / [2] yang sama sehingga titik yang dikecualikan cocok dengan kumisnya. Terima kasih lagi. Sepertinya saya perlu mempelajari lebih lanjut tentang stat_summary. - person cswingle; 22.01.2011
comment
Apakah mungkin untuk memasang kumis di ymin dan ymax? - person Caco; 17.09.2015

Berdasarkan jawaban @konvas, mulai dari ggplot2.0.x, Anda dapat memperluas ggplot menggunakan sistem ggproto dan tentukan stat Anda sendiri.

Dengan menyalin kode ggplot2 stat_boxplot dan melakukan beberapa pengeditan, Anda dapat dengan cepat menentukan stat baru (stat_boxplot_custom) yang menggunakan persentil yang ingin Anda gunakan sebagai argumen (qs) alih-alih argumen coef yang digunakan stat_boxplot. Statistik baru didefinisikan di sini:

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

Kemudian, fungsi lapisan didefinisikan. Perhatikan bahwa karena saya menyalin langsung dari stat_boxplot, Anda harus mengakses beberapa fungsi ggplot2 internal menggunakan :::. Ini mencakup banyak hal yang disalin langsung dari StatBoxplot, tetapi area kuncinya adalah menghitung statistik langsung dari argumen qs: stats <- as.numeric(stats::quantile(data$y, qs)) di dalam fungsi compute_group.

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

Ada juga inti di sini, yang berisi kode ini.

Lalu, stat_boxplot_custom bisa dipanggil seperti 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))

Contoh meluas hingga 5/95

person r_alanb    schedule 05.05.2017
comment
Jawaban ini luar biasa! Yang di atas tidak berfungsi dengan facet_grid. Ini berjalan dengan sempurna. Terima kasih banyak!! - person Marta Karas; 05.03.2018

Sekarang dimungkinkan untuk menentukan titik akhir kumis di ggplot2_2.1.0. Menyalin dari contoh di ?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"
  )

masukkan deskripsi gambar di sini

person konvas    schedule 21.07.2016