2011-01-22 43 views
22

Tôi đang cố gắng sử dụng ggplot2/geom_boxplot để tạo ra một ô mẫu nơi râu được định nghĩa là tỷ lệ phần trăm 5 và 95 thay vì 0,25 - 1,5 IQR/0,75 + IQR và các ngoại lệ từ những ria mới được vẽ như thường lệ. Tôi có thể thấy rằng tính thẩm mỹ geom_boxplot bao gồm ymax/ymin, nhưng nó không rõ ràng với tôi làm thế nào tôi đặt giá trị ở đây. Nó có vẻ như:Thay đổi định nghĩa râu trong geom_boxplot

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

sẽ có thể giúp đỡ, nhưng tôi không biết làm thế nào để liên hệ các kết quả của stat này để thiết lập geom_boxplot thích hợp() thẩm mỹ:

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

Tôi đã nhìn thấy các bài viết khác mà mọi người đề cập đến về cơ bản xây dựng một đối tượng giống như boxplot bằng tay, nhưng tôi muốn giữ nguyên toàn bộ khung hình, chỉ cần sửa lại ý nghĩa của hai biến được vẽ.

Trả lời

34

geom_boxplot với stat_summary có thể làm điều đó:

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

kohske, điều đó không thực sự thay đổi râu (cảm ơn!), Nhưng giá trị ngoại biên biến mất. – cswingle

+0

ví dụ đã được cập nhật: có nhiều cách khác nhau để làm điều đó, nhưng có lẽ đó là cách dễ nhất để vẽ các ngoại lệ trong geom_point. – kohske

+0

Tuyệt vời! Hàm o có thể sử dụng cùng một probs = c (0,05, 0,95) [1]/[2] để các điểm bị loại trừ khớp với râu. Cảm ơn một lần nữa. Có vẻ như tôi cần tìm hiểu thêm về stat_summary. – cswingle

2

Nó bây giờ có thể để xác định điểm cuối râu trong ggplot2_2.1.0. Sao chép từ các ví dụ trong ?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" 
) 

enter image description here

3

Xây dựng về câu trả lời @ konvas của, bắt đầu từ năm ggplot2.0.x, bạn có thể sử dụng hệ thống extend ggplotggproto và xác định stat của riêng bạn.

Bằng cách sao chép mã ggplot2 stat_boxplot và thực hiện một vài chỉnh sửa, bạn có thể nhanh chóng xác định một stat mới (stat_boxplot_custom) mà mất percentiles bạn muốn sử dụng như một tham số (qs) thay vì các coef luận rằng stat_boxplot sử dụng. Chỉ số mới được xác định tại đây:

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

Sau đó, chức năng lớp được xác định. Lưu ý rằng b/c tôi đã sao chép trực tiếp từ stat_boxplot, bạn phải truy cập một vài hàm ggplot2 nội bộ bằng cách sử dụng :::. Điều này bao gồm rất nhiều nội dung được sao chép trực tiếp từ StatBoxplot, nhưng khu vực chính là tính toán số liệu thống kê trực tiếp từ đối số qs: stats <- as.numeric(stats::quantile(data$y, qs)) bên trong của hàm 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 
    } 
) 

Ngoài ra còn có gist here, có chứa mã này.

Sau đó, stat_boxplot_custom có thể được gọi giống như 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)) 

Example extending to 5/95th

+0

Câu trả lời này thật tuyệt vời! Phần trên không hoạt động với facet_grid. Điều này hoàn hảo.Cảm ơn bạn một tấn !! –

Các vấn đề liên quan