科研配色与色盲友好方案
跟完这篇,您能给自己的图选对一套配色:知道数据该配顺序、发散还是定性配色,明白为什么别再用彩虹色,手里握有一份色盲也分得清的调色板,还能一句话调出 Nature、Lancet 这类期刊常见的风格——并会用代码自查「这套色红绿色盲看得清吗」。
配色不是审美问题,是准确传达数据的问题。选错一类配色,会让读者读出并不存在的分界、误判数值大小,甚至有近十分之一的男性读者根本分不清您用红绿标出的两组。好在这件事有成熟的规矩可循,照着做就能又好看又不误导人。
第一步:先看您的数据是哪一类
配色的第一决定,不是「喜欢什么颜色」,而是「数据是什么结构」。数据结构定了,配色的大类就定了,剩下的只是挑具体调色板。
| 数据结构 | 特征 | 常见例子 | 该用哪类配色 |
|---|---|---|---|
| 单向连续 | 由低到高,只有一个方向 | 表达丰度、−log10(p)、密度、计数 | 顺序(sequential) |
| 双向连续 | 有一个有意义的中点,向两边发散 | z-score、log2FC、相关系数、差值 | 发散(diverging) |
| 无序类别 | 若干并列的组,彼此没有大小 | 分组、细胞类型、亚型、通路名 | 定性(qualitative) |
记住这张表,后面全是它的展开。选之前先问自己一句:我这一列值,是「越大越……」,还是「有正有负」,还是「几个平等的类别」?
顺序、发散、定性:三类配色怎么用
顺序配色:单向的量
数据从低到高单调变化时用顺序配色——颜色由浅到深(或由暗到亮)跟着数值走。首选 viridis 系列,它感知均匀、色盲友好、灰度打印也不乱(下文详述为什么)。
library(ggplot2)
ggplot(df, aes(x, y, color = value)) +
geom_point() +
scale_color_viridis_c() # 连续型顺序配色,感知均匀、色盲友好
ColorBrewer 里的单色渐变(如 Blues、Greens、Purples)也很稳,适合热图或填色地图这类需要「一种色调、深浅表大小」的场景。
发散配色:有中点、分两个方向
数据有一个天然中点(通常是 0),向两边各表示一个方向时用发散配色。典型是「蓝—白—红」:负值蓝、中点白、正值红。关键是把中性色钉在中点上,否则红蓝深浅就失去可比性。
# 以 0 为中点的蓝-白-红发散配色(如画 log2FC、z-score)
ggplot(df, aes(x, y, fill = log2FC)) +
geom_tile() +
scale_fill_gradient2(low = "#3B4CC0", mid = "white", high = "#B40426",
midpoint = 0) # midpoint 一定要设在有意义的中点上
常用的发散调色板有 RdBu(红—蓝)、RdYlBu(红—黄—蓝)、BrBG(棕—绿)、PuOr(紫—橙)。热图里把 z-score 断点设成对称(如 ±2),配一条 RdBu 反转色带,是最通行的做法,细节见 热图聚类:注释条与配色全解。
定性配色:并列的类别
给分组、细胞类型这类无序类别上色时,要的是彼此区分度高、没有暗示大小顺序的一组色。这里别用 viridis——顺序配色采样出来,相邻类别颜色太像。改用为分类设计的调色板,比如色盲友好的 Okabe-Ito,或 ColorBrewer 的 Set2、Dark2。
# Okabe-Ito:8 色定性配色,专为色觉障碍设计(base R ≥ 4.0 内置)
okabe <- palette.colors(palette = "Okabe-Ito")
ggplot(df, aes(x, y, color = group)) +
geom_point() +
scale_color_manual(values = unname(okabe))
一条经验:定性配色的类别数越少越好。超过 7~8 类,再好的调色板也开始难分,这时考虑合并次要类别、或干脆在图上直接标名字,而不是硬塞更多颜色。
为什么别用彩虹色
彩虹色(rainbow / jet,红橙黄绿青蓝紫那条)是很多默认设置的老配色,但在数据可视化里它有三个硬伤,学界早有共识建议弃用:
- 感知不均匀。 相同大小的数值差,在不同色段看起来变化幅度不一样——绿色区一大片几乎同色、黄绿交界却陡变。结果是读者会在颜色突变处读出并不存在的边界(假边界 / banding)。
- 亮度非单调。 黄色最亮、蓝色偏暗,颜色的明暗和数值大小对不上。图一旦灰度打印或被色盲读者看到,大小关系就彻底乱了。
- 对色盲不友好。 红绿段本就是最难区分的方向,彩虹色把关键信息全压在这段上。
替换方案很简单:单向数据换 viridis(或单色渐变),双向数据换发散配色。 两者在感知均匀、亮度单调、色盲友好上都远胜彩虹色。
# 把默认/彩虹配色换成 viridis,一行的事
p + scale_color_viridis_c() # 默认 viridis
p + scale_color_viridis_c(option = "cividis") # cividis:专为色觉障碍优化的顺序配色
色盲友好:怎么选、怎么自查
先认识问题有多普遍
红绿色觉障碍是最常见的一种。常被引用的数字是约 8% 的男性、约 0.5% 的女性有某种红绿色觉障碍(主要基于北欧裔人群的统计)。换算一下:一个几十人的读者群里,几乎一定有人分不清您用纯红纯绿标出的两组。所以色盲友好不是加分项,是基本盘。
主要类型只需记两类:
| 类型 | 俗称 | 难分的方向 | 说明 |
|---|---|---|---|
| 红色盲 / 绿色盲(protan / deutan) | 红绿色盲 | 红 ↔ 绿 | 最常见,设计时重点避开纯红纯绿对比 |
| 蓝黄色盲(tritan) | 蓝黄色盲 | 蓝 ↔ 黄 | 罕见得多 |
直接选这几套,基本不出错
不想深究的话,从下面挑就行——它们都被广泛当作色盲友好的默认:
| 用途 | 调色板 | 怎么拿 |
|---|---|---|
| 顺序(连续) | viridis / cividis | scale_color_viridis_c() |
| 发散(双向) | RdBu、BrBG、PuOr | RColorBrewer::brewer.pal(11, "RdBu") |
| 定性(分类) | Okabe-Ito(最多 8 色) | palette.colors(palette = "Okabe-Ito") |
| 定性(3~8 色) | Set2 / Dark2 | RColorBrewer::brewer.pal(8, "Dark2") |
ColorBrewer 还能一次筛出所有色盲友好的调色板:
library(RColorBrewer)
display.brewer.all(colorblindFriendly = TRUE) # 只显示色盲友好的那些
再加一层保险:别只靠颜色
最稳的做法是不把区分完全押在颜色上,给同一信息叠加第二种编码,色盲读者、黑白打印都不怕:
- 散点、折线:不同组同时换形状(
shape)或线型(linetype); - 少数关键类别:干脆直接在图上标文字,不劳读者查图例对色;
- 显著性:除了颜色,再画阈值虚线或加
*标记。
用代码自查这套色
选完别凭感觉,用 colorspace 模拟一下色盲眼里的样子,一眼看出会不会撞色:
library(colorspace)
cols <- palette.colors(palette = "Okabe-Ito")[2:8] # 取一组分类色
deutan(cols) # 模拟「绿色盲」下这组色变成什么
protan(cols) # 模拟「红色盲」
# demoplot(cols, "bar") # 直接画出来预览更直观
如果模拟后有两块颜色变得几乎一样,就换掉其中一个,或叠加形状 / 标签兜底。
期刊常见配色:一键套用
审稿人和读者对某些配色有肌肉记忆——一看就知道「这是 Nature 那套」。R 里的 ggsci 包把主流期刊的配色打包成了现成的 ggplot 图层,套一行即可,省得自己调十六进制。
library(ggsci)
p + scale_color_npg() # Nature 风格
p + scale_color_lancet() # Lancet 风格
# 填充图形(柱、箱、面积)把 color 换成 fill:
p + scale_fill_nejm()
常用的几套:
| 期刊 / 风格 | 定性配色函数 |
|---|---|
| Nature(NPG) | scale_color_npg() |
| Science(AAAS) | scale_color_aaas() |
| Lancet | scale_color_lancet() |
| JAMA | scale_color_jama() |
| NEJM | scale_color_nejm() |
| 临床肿瘤(JCO) | scale_color_jco() |
两点提醒:
- 期刊配色主要是「定性配色」,适合给分组、类别上色;它们不替代顺序 / 发散配色,热图该用发散还是得用发散。
- 好看 ≠ 色盲友好。 这些期刊调色板是为观感设计的,不保证对色盲友好。用于关键的两组对比前,最好还是用上一节的
deutan()自查一遍;拿不准就退回 Okabe-Ito。
一份可以直接照抄的默认
懒得每次纠结的话,把下面这套当默认,绝大多数图都够用、也不会出错:
- 单向连续量 →
scale_*_viridis_c(); - 双向连续量(含 0) →
scale_fill_gradient2(..., midpoint = 0),蓝—白—红; - 分类 → Okabe-Ito 或
Set2;类别多就直接标签; - 要期刊感 →
ggsci挑一套,再用deutan()自查; - 永远别用 彩虹 / jet;永远别只靠颜色区分关键信息。
配色对了,图才谈得上「读得懂、经得起看」。它和轴、阈值、标注一样,是一张图能不能讲清楚事情的一部分。
在平台上跑一遍
不想记这些调色板名字、也不想写代码调色,在 百沐一下 上传数据后,用一句话说清诉求就行——比如「画分组箱线图,用色盲友好的定性配色」,或「热图用蓝白红发散配色、以 0 为中点」,或「换成 Lancet 风格配色」。智能绘图会替您选对配色大类、套好调色板并出图,您再对话式微调即可,交付时还附上可复现的 R 代码。用法见 智能绘图使用指南。
相关
- 热图聚类:注释条与配色全解 —— 发散配色、0 居中断点在热图里怎么落地
- 火山图:差异基因可视化的标准做法 —— 上下调用什么红蓝更耐看、更像期刊
- 富集分析结果怎么画 —— 气泡图、条形图里顺序配色的用法
- 智能绘图使用指南 —— 在平台上不写代码配好色、出好图