3. Seaborn基础:样式设置、绘图风格及默认调色板

Seaborn 这东西,说白了就是 Matplotlib 的「美颜滤镜」。我刚开始用 Matplotlib 画差异表达分析图时,经常花半小时调颜色、改网格、调坐标轴,结果还不好看。后来换 Seaborn,一行代码搞定样式。嗯,这节课就聊聊它的样式系统和调色板。

3.1 Seaborn 的「颜值」从哪来?

Seaborn 内置了一套完整的视觉规范。它把绘图元素拆成几个层次:主题风格决定底色和网格;上下文控制标签和线宽;调色板管理颜色映射。你想想看,这不就是给图表穿衣服吗?

我个人的习惯是,先用 sns.set_theme() 一把梭,再根据具体场景微调。但很多初学者不知道,这个方法其实是「一键重置」,会把所有样式都改掉。有一次我在项目里调了半天的字体大小,跑了一下 set_theme(),全没了……嗯,从那以后我记牢了:精细控制要用下面这些粒度更细的函数。

一句话总结:Seaborn 样式三要素 = 风格 + 上下文 + 调色板。三者独立设置,互不覆盖。

3.2 五种内置绘图风格

Seaborn 提供了 5 种开箱即用的主题。我用一个表格把它们说清楚:

风格 背景色 网格线 适用场景
darkgrid 深灰 白色细线 科研论文、数据密集散点图
whitegrid 白色 灰色细线 柱状图、箱线图、需要对照参考线的场景
dark 深灰 无 演示大屏、深色背景 PPT
white 白色 无 出版插图、干净简约风格
ticks 白色 仅坐标轴刻度线 折线图、配对比较图

使用方法很简单:

import seaborn as sns
import matplotlib.pyplot as plt

# 设置风格
sns.set_style("darkgrid")

# 画图
data = sns.load_dataset("iris")
sns.scatterplot(data=data, x="sepal_length", y="sepal_width", hue="species")
plt.show()

注意,set_style() 只影响当前图的风格,不会改调色板和字体大小。我个人最爱 whitegrid,尤其在差异表达的箱线图里,网格线能帮读者更快定位中位数和四分位距。

小技巧:可以用 sns.axes_style() 查看当前风格的完整字典。想微调某个参数?把它返回的 dict 改一改,再传给 set_style() 就行。

3.3 上下文:控制图的「胖瘦高矮」

风格管「颜值」,上下文管「身材」。Seaborn 的 set_context() 可以一键调整标签字号、线条粗细、图例大小等尺寸参数。它内置四个级别:

  1. paper —— 适合期刊论文,字小、线细
  2. notebook —— 默认值,适合 Jupyter 交互探索
  3. talk —— 适合幻灯片,字大、线粗
  4. poster —— 适合海报,超级大字号

来看看实际效果:

sns.set_context("paper")
sns.scatterplot(data=data, x="sepal_length", y="sepal_width")
plt.show()

sns.set_context("poster")
sns.scatterplot(data=data, x="sepal_length", y="sepal_width")
plt.show()

你想想看,做差异表达分析时,基因名通常很长。如果用 paper 上下文,坐标轴标签可能会挤在一起。我一般先用 talk 或者自己调大 font_scale 参数。

# 放大字体 1.5 倍,其他尺寸等比缩放
sns.set_context("notebook", font_scale=1.5)
曾经踩过的坑:有一次我在一个脚本里先后调用了 set_style() 和 set_context(),以为它俩是独立的。结果发现 set_context() 会重置部分样式参数(比如轴线颜色)。后来我改用 set_theme() 统一设置,或者先调 set_context() 再调 set_style(),才稳定下来。

3.4 默认调色板:颜色也有「性格」

调色板是 Seaborn 最让我省心的部分。它内置了多种颜色主题,适用于不同数据类型:

  • 定性调色板 —— 离散类别,比如 deep、muted、bright、pastel、dark、colorblind
  • 顺序调色板 —— 连续数值,比如 Blues、Greens、Reds 等
  • 发散调色板 —— 有中间值的连续数据,比如 RdBu、coolwarm、vlag

默认情况下,Seaborn 使用 deep 调色板。这是 6 种高饱和度但又不刺眼的颜色。我个人觉得它在差异表达火山图里表现很好,上下调基因的颜色区分度够高。

# 查看当前调色板
sns.color_palette()

# 设置调色板
sns.set_palette("muted")

# 或者一次性设置主题 + 调色板
sns.set_theme(style="whitegrid", palette="muted")

如果你想知道某个调色板长什么样,用 sns.palplot() 直接可视化:

sns.palplot(sns.color_palette("Blues", 8))
plt.show()
核心原则:定性数据用定性调色板,连续数据用顺序或发散调色板。别搞混。我曾经见过有人用 RdBu 去画 5 个离散的基因簇,结果颜色过渡让人误以为中间有「中间状态」……误导性很强。

3.5 用 SVG 看 Seaborn 样式体系

下面这张图我画了 Seaborn 样式系统的整体结构。你跟着它走,基本不会迷路:

Seaborn 样式体系 sns.set_style() sns.set_context() sns.set_palette() darkgrid whitegrid dark white ticks paper notebook talk poster 定性(6种) 顺序(多组) 发散(多组) 自定义 统一入口:sns.set_theme() style="whitegrid", context="notebook", palette="muted" 一行搞定全部样式设置,推荐用于项目初始化 💡 我的日常配方 差异表达分析图:whitegrid + talk 上下文 + muted 调色板 火山图:darkgrid + poster 上下文 + RdBu 发散调色板

3.6 实战:快速搭建差异表达图的样式基底

讲完概念,咱们直接上手。假设你刚拿到一个差异表达数据框,里面有 log2FC 和 pvalue 两列。按我的习惯,先搭样式框架:

import seaborn as sns
import matplotlib.pyplot as plt
import pandas as pd
import numpy as np

# 1. 用 set_theme 统一初始化
sns.set_theme(
    style="whitegrid",
    context="talk",
    palette="muted",
    font="sans-serif",
    font_scale=1.2
)

# 2. 模拟差异表达数据
np.random.seed(42)
n = 500
df = pd.DataFrame({
    "log2FC": np.random.randn(n) * 2,
    "pvalue": np.random.chisquare(2, n) / 10,
    "gene": [f"Gene_{i}" for i in range(n)]
})
df["-log10(pvalue)"] = -np.log10(df["pvalue"] + 1e-10)

# 3. 画火山图(示意)
sns.scatterplot(data=df, x="log2FC", y="-log10(pvalue)", alpha=0.6)
plt.xlabel("log2 Fold Change")
plt.ylabel("-log10(pvalue)")
plt.title("Volcano Plot — DE Genes")
plt.show()

这段代码你复制到 Jupyter 里就能跑。注意 set_theme 里的 font_scale 参数——我习惯设到 1.2 到 1.5 之间,这样在幻灯片上不用眯眼看坐标轴标签。

个人偏好:如果你跟我一样经常用 whitegrid,建议把网格线色调调淡一点点。默认的灰色在某些显示器上有点抢眼。可以用 sns.set_style("whitegrid", {"grid.color": ".9"}) 把网格变成浅灰。

3.7 三个让我少加班的小经验

最后分享几个实际项目里攒下来的经验,希望对你有帮助:

  • 配置文件统一管理样式 —— 我会把 set_theme 的参数写在一个 YAML 文件里,不同项目(论文、PPT、海报)用不同的配置文件。这样改样式时不用翻代码。
  • 调色板要照顾色盲读者 —— 差异表达分析里常用红绿表示上下调,但红绿色盲群体很常见。我现在改用 colorblind 调色板或者 RdBu,蓝橙对比对色盲更友好。
  • 别频繁切换上下文 —— 同一个报告里,所有图的上下文最好统一。我见过有人前半段用 paper,后半段用 talk,放在一起对比时字号忽大忽小,很掉档次。
曾经踩过的坑:有一次我用了 sns.set_palette("Blues"),以为只改了颜色。结果它把调色板从原来的 6 种颜色缩减成单一色系的渐变。当我画一个包含 5 个分类的箱线图时,第 2 类和第 4 类的颜色几乎一样……后来我改用 sns.color_palette("Blues", 5) 显式指定颜色数量才解决。记住:set_palette 不带数量参数时,会用调色板的默认颜色数,顺序调色板默认只有 6 档。

好了,Seaborn 的样式系统就聊到这儿。你把它当成一个「主题包 + 尺寸控制器 + 颜色库」的组合拳就行。上手练两遍,你绘图效率至少能提一倍。