Introduction
箱线图用五个视觉部件压缩一组连续数据:中位数、上下四分位数、两条须,以及落在须外的点。它适合并排比较多个组的位置与离散程度,比均值柱保留的信息多,也比小提琴图更少依赖分布估计。
关心双峰、偏态尾部或完整密度形状时用小提琴图或密度图;只展示一个估计值和不确定性时用点估计加误差棒。箱线图不是所有"组间比较"的默认答案。
读的时候按这个顺序:
- 箱体下边缘是 Q1,上边缘是 Q3。 中间 50% 的数据落在箱体内。
- 箱体高度是 IQR = Q3 − Q1。 箱体越高,中间一半数据越分散。
- 箱内横线是中位数,不是均值。 偏态数据里两者可以相差很远。
- 须不是最小值和最大值。 下须延伸到不低于
Q1 − 1.5 × IQR的最小观测,上须延伸到不高于Q3 + 1.5 × IQR的最大观测——围栏只是判定界限,须端落在真实观测上,不一定正好等于围栏位置。 - 须外的点是规则标出的潜在异常值。 它们不一定错误,也不能因为被标出就删掉。
Example Data
箱线图要的输入是:1 个分类变量 + 1 个连续数值变量,一行一个观测。不需要事先汇总——四分位和须都是绘图层现算的。
plant_growth 有一个对照组和两个处理组,每组恰好十株植物。每组只有十来个观测时,几个分位数会被单个点明显影响,所以这一页的主版本会把全部原始点叠上去。
library(ggplot2)
library(ggpubr)
library(biopalette)
# 公开地址,和数据集页上「下载 CSV」给的是同一个 —— 不写仓库相对路径:
# 那个目录不进仓库,读者 clone 下来也没有这个文件,这段代码就跑不了
d <- read.csv("https://assets.evanzhou.org/tessera/csv/plant_growth.csv")
# 显式定 levels:ctrl 必须排在两个处理组前面,交给字母序也对,但换套组名就不对了
group_levels <- c("ctrl", "trt1", "trt2")
d$group <- factor(d$group, levels = group_levels)
# 样本量写进 x 轴标签 —— 同样大小的箱体可能来自 10 个点或 1000 个点,
# 而箱线图本身不透露这件事
group_n <- table(d$group)
group_labels <- setNames(
paste0(group_levels, "\n(n=", as.integer(group_n[group_levels]), ")"),
group_levels
)
Palettes
处理组是无序类别,用定性色板 walter_white2。箱体用半透明填色配统一深色边框,原始点沿用同一组颜色和同一种圆形——颜色只解释组别一次。
箱线图里的色块面积比散点大,所以浅色很容易显得发白,深色又可能压住中位数线。保留深色轮廓加适度透明度,比单纯加深所有颜色更稳。
常规分组箱线图只用颜色。再给每组配一种点形,是增加一份没有新信息的图例负担。色板不足组数时不循环颜色,也不删数据:未编码的组用明确的中性色。
group_colors <- setNames(
get_palette("walter_white2", type = "qualitative")[1:3],
group_levels
)
# 四张图共用同一条 y 轴:箱体高低要横着比,坐标就不能各画各的
box_scale <- scale_y_continuous(
breaks = seq(3.5, 6.5, 1),
expand = expansion(mult = c(0.04, 0.06))
)
box_theme <- theme_pubr(base_size = 13, legend = "none") +
theme(
panel.grid.major.y = element_line(color = "#E5E3DC", linewidth = 0.35),
panel.grid.major.x = element_blank(),
axis.line = element_line(color = "#333330", linewidth = 0.45),
axis.ticks = element_line(color = "#333330", linewidth = 0.4),
plot.title = element_text(face = "bold", size = 15, hjust = 0),
plot.subtitle = element_text(color = "grey35", hjust = 0),
plot.margin = margin(14, 16, 12, 12)
)
Recipe
| No. | Method | Input Data | Palettes |
|---|---|---|---|
| 1 | ggplot2 |
d |
— |
| 2 | ggplot2 |
d |
group_colors |
| 3 | ggplot2 |
d |
group_colors |
| 4 | ggplot2 |
d |
group_colors |
1 · 基础分组箱线图
先只看统计结构。三个组已经由横轴位置区分,不需要图例,也不需要颜色。
#| fig: basic
#| fig-width: 7.5
#| fig-height: 5.2
ggplot(d, aes(group, weight)) +
geom_boxplot(
width = 0.56,
fill = NA, # 完全不填色,只留轮廓、中位数和须
color = "#333330",
linewidth = 0.7
) +
scale_x_discrete(labels = group_labels) + # 带 n 的标签
box_scale +
labs(
title = "Plant weight by treatment",
subtitle = "Outline only · no box fill",
x = NULL,
y = "Dried weight"
) +
box_theme


