【问题标题】:How to create a boxplot with customized quantiles in R?如何在 R 中创建带有自定义分位数的箱线图?
【发布时间】:2019-10-22 13:31:52
【问题描述】:

我现在正在处理一些数据,我想制作一个显示最小值、2.5、25、50、70、75、97.5 和最大值的箱线图。箱线图还应该有一个图例,显示不同颜色的线条来代表每个分位数。有没有办法做到这一点?感谢您的帮助。

set.seed(123)
Mydata = sample(x=100:300, size = 500, replace = T)
Mydata = c(Mydata, 1, 500)
boxplot(Mydata)

PS。我已经尝试过@thelatemail 提供的代码,但在 RStudio 中得到了完全不同的数字。有什么解决办法吗?谢谢。

【问题讨论】:

  • 哪些分位数应该显示在“方框”中,哪些分位数应该显示在“晶须”中?传统的箱线图只在方框中显示 25 到 75,然后对于如何显示之外的数据有一些稍微复杂的规则。
  • @Marius 嗨,我想把 2.5、25、50、70、75、97.5 放在“盒子”中,而最小值和最大值作为“晶须”。你能帮我解决这个问题吗?谢谢。

标签: r boxplot quantile


【解决方案1】:

使用bxp 继续重复绘制:

set.seed(123)
Mydata = sample(x=100:300, size = 500, replace = T)
Mydata = c(Mydata, 1, 500)

bp <- boxplot(Mydata, range=0, plot=FALSE)

vals <- c(
  min=min(Mydata),
  quantile(Mydata, c(0.025, 0.25, 0.5, 0.7, 0.75, 0.975)),
  max=max(Mydata)
)

bxp(bp, whisklty=0, staplelty=0)
bp$stats[2:4,] <- c(vals[2], Inf, vals[5])
bxp(bp, whisklty=0, staplelty=0, add=TRUE)
bp$stats[2:4,] <- c(vals[2], Inf, vals[7])
bxp(bp, whisklty=1, staplelty=1, add=TRUE)

【讨论】:

  • 您好,感谢您的帮助。我试过你的代码,但它产生的数字与你的完全不同。你能查一下吗?
  • @YangYang - 我刚刚运行它并得到了与所示相同的结果。您是否关闭了现有的箱线图窗口?这段代码需要从头开始。
  • 您好,我注意到您的代码在 RGui 中有效,但在 RStudio 中无效。很奇怪......你能不能试着让代码在 RStudio 中也能工作?谢谢。
  • @YangYang - 首先运行dev.new() 打开一个图形窗口,然后运行上面的代码。 RStudio 显然不尊重代码的add=TRUE 部分,并且每次都会生成一个全新的绘图。这似乎是 RStudio 的错误。
  • 您好,我在您的代码前添加了dev.new(),但它在 RStudio 中仍然不起作用。也许我们必须使用 RGui?
【解决方案2】:

使用箱线图框架无法轻松生成您想要做的事情。

R 中的基础箱线图是 boxplot.stats() 函数。让我们在您的数据上运行它:

boxplot.stats(Mydata)

$stats
[1]   1 152 204 253 300

$n
[1] 502

$conf
[1] 196.8776 211.1224

$out
[1] 500

您可以看到$stats 按顺序返回:下须线、25% 分位数、中位数、75% 分位数、上须线。与quantile比较:

quantile(Mydata)

  0%  25%  50%  75% 100% 
   1  152  204  253  500

如果您使用来自ggplot2geom_boxplot(),则可以重新定义用于该框的值。但你只能绘制相同的五个值:它们分别称为yminlowermiddleupperymax

例如,如果您希望将 2.5% 的分位数设为 lower,将 97.5% 的分位数设为 upper,您可以尝试:

data.frame(x = 1,
           y0 = min(Mydata),
           y025 = quantile(Mydata, 0.025),
           y50 = median(Mydata),
           y975 = quantile(Mydata, 0.975),
           y100 = max(Mydata)) %>%
  ggplot(df, aes(x)) +
  geom_boxplot(aes(ymin = y0, 
                   lower = y025, 
                   middle = y50, 
                   upper = y975, 
                   ymax = y100),
               stat = "identity")

但是,您需要明确说明(可能使用标签)这不是“标准”箱线图。

另一个ggplot2 的想法是使用geom_jitter 绘制数据点,然后使用geom_hline 为所需的分位数添加线条。像这样的:

library(tibble)
library(ggplot2)

Mydataq <- quantile(Mydata, probs = c(0.025, 0.25, 0.5, 0.7, 0.75, 0.975)) %>%
  as.data.frame() %>% 
  setNames("value") %>% 
  rownames_to_column(var = "quantile")

Mydataq %>% 
  ggplot() + 
  geom_hline(aes(yintercept = value, color = quantile)) + 
  geom_jitter(data = tibble(x = "Mydata", y = Mydata), 
              aes(x = x, y = y))

【讨论】:

  • 非常感谢您的帮助。是否可以在“盒子”中绘制 2.5、25、50、70、75、97.5,而最小值和最大值为“晶须”,就像 6 条直线的箱线图一样?
  • 不使用geom_boxplot。您也许可以使用其他一些图形功能自己构建盒子。
【解决方案3】:

这是一个想法。您可能需要进一步完善它。

#Data
P = c(2.5, 25, 50, 70, 75, 97.5)

#Quantiles
b = quantile(x = Mydata, probs = P/100)

#Custom funtion
dp = function(at, y1, y2, width, ...){
    polygon(x = c(at - width/2, at + width/2, at + width/2, at - width/2),
            y = c(y1, y1, y2, y2), ...)
}

#Parameters
at = 1
width = 0.2

graphics.off()

#Whiskers
plot(x = rep(at, length(Mydata)), y = Mydata, type = "l")
segments(x0 = at - width/2, x1 = at + width/2, y0 = min(Mydata), y1 = min(Mydata))
segments(x0 = at - width/2, x1 = at + width/2, y0 = max(Mydata), y1 = max(Mydata))

#Boxes
sapply(1:ceiling(length(b)/2), function(i) {
    dp(at = at, y1 = b[i], y2 = b[length(b) + 1 - i], width = width * i, col = i)
})
#OR
sapply(1:ceiling(length(b)/2), function(i) {
    segments(x0 = at, x1 = at, y0 = b[i], y1 = b[length(b) + 1 - i],
             lwd = 10 * i, col = i, lend = "butt")
})

【讨论】:

  • 感谢您的帮助。你能用线代替多边形吗?可能会更好...
猜你喜欢
  • 1970-01-01
  • 2018-05-13
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-08-22
  • 1970-01-01
相关资源
最近更新 更多