HOWTO · Seaborn
如何创建 Seaborn 折线图
本教程演示如何使用 Seaborn 模块在 Python 中创建折线图。学习如何使用可自定义的折线图、置信区间和多条线进行比较分析,从而有效地可视化数据。无论是初学者还是希望提高数据可视化技能的经验丰富的用户,都非常适合。
本页内容
Seaborn 折线图将 x 变量和 y 变量的值映射到由一条线连接的点。它常用于时间序列,但 x 可以是任何有序或连续变量。seaborn.lineplot() 函数还可以汇总重复的观测,并为不同类别绘制单独的线,因此有助于探索测量值如何变化并比较不同组。
Seaborn 入门
Seaborn 是一个建立在 Matplotlib 之上的统计绘图库。下面的示例使用 pandas DataFrame,这是一种将命名列放在一起的便捷方式。如果你的 Python 环境中还没有 Seaborn 及其依赖项,请先安装它们;然后导入 Seaborn 和 Matplotlib。绘图示例中不需要单独的安装命令。
本教程中的示例已使用 Python 3.12 上的 Seaborn 0.13.2、Matplotlib 3.11.2 和 pandas 3.1.0 运行并验证,下面的每个图都是这些示例实际生成的输出。
创建基本折线图
将 DataFrame 传递给 data,并为 x 和 y 指定列名。下面的示例使用固定值,因此绘制的点是可重现的。调用 plt.show() 会在交互式环境中打开图形;在笔记本中,图形通常显示为单元格的结果。
运行此示例:
import pandas as pd
import seaborn as sns
import matplotlib.pyplot as plt
data = pd.DataFrame({
"day": [1, 2, 3, 4, 5],
"visitors": [12, 15, 13, 18, 21],
})
sns.lineplot(data=data, x="day", y="visitors")
plt.xlabel("Day")
plt.ylabel("Visitors")
plt.title("Visitors by day")
plt.tight_layout()
plt.show()
横轴使用 day,纵轴使用 visitors。将这些名称和值替换为你自己表格中的列。如果多行共享同一个 x 值,Seaborn 可能会聚合该位置的 y 观测值并显示不确定性带;接下来的几个部分将解释如何解读这些特征。
自定义折线图
外观设置可帮助读者区分一个系列或跟踪其值。例如,color 设置线条颜色,marker 在每个观测处放置一个符号,linestyle 更改线条的描边样式。这些是视觉上的选择;它们不会创建分组,也不会改变哪些行属于数据。请选择在图形将被阅读的尺寸下仍易于区分的颜色和标记。
在包含导入和 data 定义的脚本中使用与上面相同的确定性表格。这个完整变体用虚线强调各点:
import pandas as pd
import seaborn as sns
import matplotlib.pyplot as plt
data = pd.DataFrame({
"day": [1, 2, 3, 4, 5],
"visitors": [12, 15, 13, 18, 21],
})
sns.lineplot(data=data, x="day", y="visitors", color="darkorange", marker="o", linestyle="--")
plt.xlabel("Day")
plt.ylabel("Visitors")
plt.title("Visitors by day")
plt.tight_layout()
plt.show()
如需不同的外观,可更改这些参数,或使用 Matplotlib 方法设置标签和标题。保持 x 和 y 的映射明确,以便后来的读者能知道每个点代表什么。
添加置信区间
线条周围的不确定性带汇总了估计周围的变异或不确定性。其含义取决于数据和估计量:当多个观测对某个 x 位置有贡献时,中心线可能会对它们进行汇总,而带则传达了该汇总周围的不确定性。它不仅仅是标准差的另一个名称。标准差描述观测之间的离散程度;置信区间描述的是一个估计量的不确定性。
下面的示例为每一天提供三个观测值。代码首先打印每个组的平均值,这样你就可以将绘制的线与简单的数字进行核对:
import pandas as pd
import seaborn as sns
import matplotlib.pyplot as plt
data = pd.DataFrame({
"day": [1, 1, 1, 2, 2, 2, 3, 3, 3, 4, 4, 4],
"visitors": [10, 12, 14, 14, 16, 18, 13, 15, 17, 19, 21, 23],
})
print(data.groupby("day")["visitors"].mean())
sns.lineplot(data=data, x="day", y="visitors", marker="o")
plt.xlabel("Day")
plt.ylabel("Visitors")
plt.title("Mean visitors by day with 95% confidence band")
plt.tight_layout()
plt.show()
输出:
day
1 12.0
2 16.0
3 15.0
4 21.0
Name: visitors, dtype: float64
中心线穿过打印出的平均值(12、16、15 和 21):当存在重复观测时,lineplot() 默认使用平均值聚合每个 x 组。阴影带是该平均值的 95% 置信区间,通过自助法(bootstrapping)计算。某个组的分布越分散,带就越宽;它并不能说明单个观测值落在何处。
在解读一条带之前,请检查每个 x 值是否有重复的观测,以及这些观测代表什么。例如,来自同一受试者的重复测量并不一定代表独立样本。当每个 x 值只有一个观测时,就不存在可据以以同样方式推断变异的位置内重复。合适的解读还取决于所使用的 Seaborn 版本和绘图选项。这里的示例使用 errorbar 参数,该参数自 Seaborn 0.12 起可用;在 Seaborn 0.13.2 中,默认值为 errorbar=("ci", 95),而 errorbar="sd" 则会改为绘制一条在平均值两侧各跨一个标准差的带。当你需要控制估计量或区间方法时,请查阅已安装版本的文档。如果该带对你的数据没有意义,请相应配置图形,或将其省略,并说明该线是如何计算的。
当带没有意义时,可使用 errorbar=None 将其关闭。聚合仍会发生——线仍会连接各组的平均值——但不会绘制任何带:
import pandas as pd
import seaborn as sns
import matplotlib.pyplot as plt
data = pd.DataFrame({
"day": [1, 1, 1, 2, 2, 2, 3, 3, 3, 4, 4, 4],
"visitors": [10, 12, 14, 14, 16, 18, 13, 15, 17, 19, 21, 23],
})
sns.lineplot(data=data, x="day", y="visitors", marker="o", errorbar=None)
plt.xlabel("Day")
plt.ylabel("Visitors")
plt.title("Mean visitors by day without uncertainty band")
plt.tight_layout()
plt.show()
这两个图绘制的是相同的平均值;区别仅在于带。根据不确定性汇总是否有助于读者来在两者之间选择,而不是看哪个图看起来更干净。
绘制多条线
对于基于类别的比较,请包含一个类别列并将其映射到 hue。Seaborn 会为每个类别绘制一条单独的彩色线并添加图例。当线条样式可提供额外的视觉区分时,将 style 映射到相同或另一个类别列。仅当各行共享相同的 x 和 y 度量时才使用类别;保持各组之间的标签和单位一致。
以下是一个使用固定观测值的完整分组数据示例:
import pandas as pd
import seaborn as sns
import matplotlib.pyplot as plt
data = pd.DataFrame({
"week": [1, 2, 3, 1, 2, 3],
"orders": [8, 11, 14, 6, 9, 10],
"store": ["North", "North", "North", "South", "South", "South"],
})
sns.lineplot(data=data, x="week", y="orders", hue="store", style="store", markers=True, dashes=True)
plt.xlabel("Week")
plt.ylabel("Orders")
plt.title("Orders by store")
plt.tight_layout()
plt.show()
当数据改为每个系列有单独的数值列时,将其重塑为一张长表,其中包含一个值列和一个系列名称列,然后将系列名称映射到 hue。或者,将每个 y 列绘制在共享的 Matplotlib 坐标轴上,并在添加图例前为每条线指定一个标签。无论哪种方法,图例都应标识每条线并与其数据相符。不要使用类别样式来掩盖不同的单位或尺度;当直接比较会产生误导时,请考虑使用单独的坐标轴或单独的图形。
修复拼写错误的列名
传递给 x 和 y 的名称必须与 data 中的列名完全一致。如果名称拼写错误,lineplot() 会在绘制任何内容之前引发错误。此调用要求一个名为 visitor 的列,但 DataFrame 中只有 visitors:
import pandas as pd
import seaborn as sns
data = pd.DataFrame({
"day": [1, 2, 3, 4, 5],
"visitors": [12, 15, 13, 18, 21],
})
sns.lineplot(data=data, x="day", y="visitor")
输出:
ValueError: Could not interpret value `visitor` for `y`. An entry with this name does not appear in `data`.
该消息指明了参数(y)、失败的值(visitor)和原因,因此这个错误很容易修复:将名称与实际列进行比较——打印 data.columns 即可列出它们——然后更正拼写。对于 x 或拼写错误的 hue 或 style 列,也会出现同样的错误。
结论
使用 seaborn.lineplot() 沿 x 值连接 y 的测量值,然后选择外观设置或类别映射,使图形易于阅读。在解读不确定性带之前,请检查重复观测是如何汇总的,并为每个被比较的系列明确添加标签。
常见问题
- Seaborn 为 Matplotlib 增加了什么? Seaborn 提供了用于统计图形的高级接口,并与 Matplotlib 协同工作,以显示图形和进一步格式化。
- 我可以传递 pandas DataFrame 吗? 可以。将
data设置为 DataFrame 并将列名传递给x和y。 - 如何更改线条外观? 使用
color、marker和linestyle等选项;这些选项更改外观,而hue将类别映射到单独的线。 - 阴影带是什么意思? 它表示与所绘制估计相关的不确定性汇总。其解读取决于重复观测、估计量和所选的区间方法;它并不自动就是标准差。
- 如何比较多条线? 将类别列映射到
hue,或者在共享坐标轴上绘制单独标记的系列。确保图例准确命名每条线。 - 如何移除阴影带? 传递
errorbar=None。该线仍会使用平均值聚合重复观测;只是省略了不确定性带。