You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

R语言如何绘制无上下四分位数、须间垂连的定制箱线图

定制极简箱线图:仅保留中位数与异常值

嘿,我明白你想要的是一种极简风格的箱线图——只保留中位数和异常值,用须把中位数和异常值的范围连起来,还要在须的两端加小垂直线对吧?我来给你两种实现方式,一种用基础R,另一种用ggplot2,你可以挑顺手的来:

方法一:基础R实现

基础R的boxplot()函数本身有不少可调整的参数,我们可以先隐藏掉不需要的元素,再手动添加自定义的须和垂直线:

# 先获取箱线图的统计数据(不绘图)
bp_stats <- boxplot(mpg ~ cyl, data = mtcars, plot = FALSE)

# 绘制空坐标轴,只保留中位数点
plot(
  x = 1:length(unique(mtcars$cyl)), 
  y = bp_stats$stats[3,],  # 3号位置是中位数
  xlim = c(0.5, length(unique(mtcars$cyl)) + 0.5),
  ylim = range(c(bp_stats$stats, bp_stats$out)),  # 包含所有值和异常值的范围
  xlab = "Number of Cylinders",
  ylab = "Miles Per Gallon",
  main = "Car Milage Data",
  xaxt = "n",  # 先不画x轴刻度
  pch = 16,    # 中位数用实心圆点
  cex = 1.2    # 放大中位数点
)

# 添加x轴刻度
axis(1, at = 1:length(unique(mtcars$cyl)), labels = unique(mtcars$cyl))

# 循环给每个组添加须和垂直线
for (i in 1:length(unique(mtcars$cyl))) {
  # 筛选当前组的异常值
  group_outliers <- bp_stats$out[bp_stats$group == i]
  
  if (length(group_outliers) > 0) {
    # 画连接中位数到异常值最小值、最大值的须
    lines(c(i, i), c(bp_stats$stats[3, i], min(group_outliers)), lty = 1)
    lines(c(i, i), c(bp_stats$stats[3, i], max(group_outliers)), lty = 1)
    
    # 在须的两端添加小垂直线
    lines(c(i - 0.1, i + 0.1), c(min(group_outliers), min(group_outliers)))
    lines(c(i - 0.1, i + 0.1), c(max(group_outliers), max(group_outliers)))
  }
}

# 添加异常值点(用红色突出)
points(bp_stats$group, bp_stats$out, pch = 19, col = "red")

或者更偷懒一点,直接用boxplot()的参数隐藏箱子和默认须,再补画自定义元素:

# 先画基础图,隐藏箱子、默认须和须端垂直线,只保留中位数和异常值
boxplot(mpg ~ cyl, data = mtcars,
        main = "Car Milage Data",
        xlab = "Number of Cylinders",
        ylab = "Miles Per Gallon",
        boxwex = 0,        # 箱子宽度设为0,隐藏箱子
        whisklty = 0,      # 隐藏默认的须
        staplelty = 0,     # 隐藏默认须的垂直线
        outline = TRUE,    # 保留异常值点
        medlwd = 2)        # 加粗中位数线

# 同样获取统计数据,补画自定义须和垂直线
bp_stats <- boxplot(mpg ~ cyl, data = mtcars, plot = FALSE)
for (i in 1:length(unique(mtcars$cyl))) {
  group_outliers <- bp_stats$out[bp_stats$group == i]
  if (length(group_outliers) > 0) {
    lines(c(i, i), c(bp_stats$stats[3, i], min(group_outliers)))
    lines(c(i, i), c(bp_stats$stats[3, i], max(group_outliers)))
    lines(c(i - 0.1, i + 0.1), c(min(group_outliers), min(group_outliers)))
    lines(c(i - 0.1, i + 0.1), c(max(group_outliers), max(group_outliers)))
  }
}

方法二:ggplot2实现

如果你习惯用ggplot2,这种定制化的图会更灵活,我们可以分步构建每个元素:

library(ggplot2)
library(dplyr)
library(tidyr)

# 先计算每个气缸组的中位数、异常值范围
mtcars_custom <- mtcars %>%
  group_by(cyl) %>%
  mutate(
    med = median(mpg),
    q1 = quantile(mpg, 0.25),
    q3 = quantile(mpg, 0.75),
    iqr = q3 - q1,
    lower_bound = q1 - 1.5 * iqr,
    upper_bound = q3 + 1.5 * iqr
  ) %>%
  # 筛选出异常值
  filter(mpg < lower_bound | mpg > upper_bound) %>%
  group_by(cyl) %>%
  summarise(
    med = unique(med),
    min_out = min(mpg),
    max_out = max(mpg),
    outliers = list(mpg)
  ) %>%
  unnest(outliers)  # 展开异常值列表

# 构建图形
ggplot() +
  # 添加异常值点
  geom_point(data = mtcars_custom,
             aes(x = factor(cyl), y = outliers),
             color = "red", size = 2) +
  # 添加中位数点
  geom_point(data = mtcars_custom %>% distinct(cyl, med),
             aes(x = factor(cyl), y = med),
             shape = 16, size = 3) +
  # 画连接中位数到异常值最小值的须
  geom_segment(data = mtcars_custom %>% distinct(cyl, med, min_out),
               aes(x = factor(cyl), xend = factor(cyl),
                   y = med, yend = min_out)) +
  # 画连接中位数到异常值最大值的须
  geom_segment(data = mtcars_custom %>% distinct(cyl, med, max_out),
               aes(x = factor(cyl), xend = factor(cyl),
                   y = med, yend = max_out)) +
  # 须下端的垂直线
  geom_segment(data = mtcars_custom %>% distinct(cyl, min_out),
               aes(x = as.numeric(factor(cyl)) - 0.1,
                   xend = as.numeric(factor(cyl)) + 0.1,
                   y = min_out, yend = min_out)) +
  # 须上端的垂直线
  geom_segment(data = mtcars_custom %>% distinct(cyl, max_out),
               aes(x = as.numeric(factor(cyl)) - 0.1,
                   xend = as.numeric(factor(cyl)) + 0.1,
                   y = max_out, yend = max_out)) +
  # 添加标题和坐标轴标签
  labs(title = "Car Milage Data",
       x = "Number of Cylinders",
       y = "Miles Per Gallon") +
  theme_bw()  # 用简洁的主题

两种方法都能实现你要的效果,基础R不需要额外包,ggplot2则更便于后续调整样式~

内容的提问来源于stack exchange,提问作者RAHenriksen

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.25 07:12:31