数据的重要特征仅仅可见是不够的,它必须引人注目。
拒绝感知差异,画出实际差异
-
感知差异:当我们尝试比较折线图中的两条线时,我们通常将差异感知为 线条之间的最短距离。
-
实际差异:但是,特定水平位置处的实际差异是 两条线之间的垂直差异。
-
画出差异:我们不需要依靠眼睛来填充空间,而是可以 画出垂直标记来明确实际差异。
-
共同基线:此外,通过 将垂直标记放在共同基线上,随着时间的推移,差异变得更容易比较。
当 比较两个指标随时间的变化 时,标准做法是 画出两条线并寻找差距。但是,如果差异最为重要,则应将差异可视化,以便清楚了解。
虽然它是时间序列数据,但它不一定是折线图
接下来,展示一位分析师的思维过程和最佳实践,他使用可观察的图表揭示了德克萨斯州能源发电异常激增背后隐藏的模式。
当深入研究数据集时,能够使用可视化快速生成 不同的视角 会产生很大的不同。
哪种图表“最好”取决于数据。不同的标记或图表类型揭示了数据的不同方面。
接下来重点介绍 每个图表的有效性如何受到数据本身特征的影响,以及 如何通过一系列细微的调整将基本图表转变为清晰揭示数据最重要方面的图表。
分析并可视化相关性和随时间的变化
如何 评估两个变量随时间的变化关系?有许多方法可以分析相关性,并可视化数据集随时间的变化。
但是,当 需要同时了解时间和相关性时,该怎么办:看看两个指标之间的相关性在不同时间段内如何变化?
从 仅使用颜色标记散点图中的类别 切换到 按类别进行分面。生成的迷你图表(每个时间段一个)揭示了 细微的基于时间的分布模式,而这在标准方法中几乎是不可能看到的。
参考:How to analyze and visualize time series data
扩展
-
堆叠面积图
在面积图中,多个变量“堆叠”在一起,每条线下方的区域都 用颜色表示每个变量。
下图用堆叠面积图显示了 2001 年至 2010 年印度学生入学时间序列数据。
堆积面积图可用于显示 累计总数 和 总数的各个组成部分 随时间的变化情况。
变量堆叠的顺序 至关重要,因为实际图表与人类感知有时会有所不同。
-
流图
流图本质上是 堆叠面积图,但 围绕中心水平轴移动。流图看起来像流动的液体,因此得名。
流图非常适合表示和比较 多个变量 的 时间序列 数据。因此,流图适合大型数据集。请记住,颜色的选择 非常重要,尤其是在变量很多的情况下。如果颜色选择不当,没有明显高值的变量可能会在可视化中被淹没。
下面是一个流图,显示了随机选择的听众在一段时间内的音乐收听习惯。
-
使用的 seaborn 组件:
set_theme()
,load_dataset()
,lineplot()
import seaborn as sns sns.set_theme(style="darkgrid") # Load an example dataset with long-form data fmri = sns.load_dataset("fmri") # Plot the responses for different events and regions sns.lineplot(x="timepoint", y="signal", hue="region", style="event", data=fmri)
Seaborn 是一个基于 matplotlib 的 Python 数据可视化库。它提供了一个高级界面,用于绘制有吸引力且信息丰富的统计图形。
实战
现在有很多电压序列 V 和 位置 Z 的时间序列轨迹,从两种视角来进行数据统计绘制,
-
全体样本点的分布 视角:直接把 所有样本点(每个时刻、每条轨迹)都展开,做散点和 KDE,是真正的、整个样本的分布。
-
均值的95%置信区间 视角:
- 聚合:会先 对每个时间点把所有轨迹上的值拿来「算一个均值」,然后画这条均值线。
- 置信区间:接着画的是 「均值的95%置信区间」(95% CI of the mean),而不是「数据本身的分布宽度」。当样本数 NV 很大时,置信区间带会非常窄,哪怕原始分布在 ±1000 V 里,CI 也可能只有 ±100 V 这么宽。
“95% 置信区间”带(confidence interval, CI)画的是“均值的置信区间”——也就是 x ˉ ( t ) ± z 0.975 s ( t ) N \bar x(t) \pm z_{0.975}\,\frac{s(t)}{\sqrt{N}} xˉ(t)±z0.975Ns(t)
- x ˉ ( t ) \bar x(t) xˉ(t) 是在时刻 t t t 对所有 N N N 条轨迹求得的平均值,
- s ( t ) s(t) s(t) 是它们在该时刻的样本标准差,
- s ( t ) N \frac{s(t)}{\sqrt{N}} Ns(t) 是平均值的标准误(standard error),
- z 0.975 ≈ 1.96 z_{0.975}\approx1.96 z0.975≈1.96(或用 t 分布)决定 95% 的置信系数。
所以即便单条轨迹的电压分布在 ±1000 V,一个很常见的情形是:
s ≃ 800 # 单时刻样本标准差约 800 V
N ≃ 100 # 比如有 100 条轨迹
se = s/√N ≃ 800/10 = 80 V
CI_half_width ≃ 1.96 × se ≃ 1.96×80 ≃ 157 V
于是阴影带只在 ±150 V 左右,而不是 ±1000 V。样本量越大, N \sqrt{N} N 越大,带子就越窄。
如果想 让阴影反映“原始分布的波动” 而不是“均值的精度”,可以改用:
-
标准差带(±1σ)
sns.lineplot( x='Time', y='Z', data=df_z, estimator='mean', errorbar='sd', # 用标准差 ax=ax1 ) sns.lineplot( x='Time', y='V', data=df_v, estimator='mean', errorbar='sd', ax=ax2, linestyle='--' )
阴影就会是“均值 ± 1 个样本标准差”,大致覆盖 68% 的数据。
-
分位区间带(比如 2.5%–97.5%)
sns.lineplot( x='Time', y='Z', data=df_z, estimator='mean', errorbar=('quantile', [0.025, 0.975]), ax=ax1 ) sns.lineplot( x='Time', y='V', data=df_v, estimator='mean', errorbar=('quantile', [0.025, 0.975]), ax=ax2, linestyle='--' )
这时阴影会真正反映上下 95% 样本的“分布宽度”。