统计分析是了解数据集中的变量如何相互关联以及这些关系如何依赖于其他变量的过程。可视化可以成为此过程的核心组成部分,因为当数据正确可视化时,人类视觉系统可以看到表明关系的趋势和模式。
在本教程中,我们将讨论三个 seaborn 函数。我们最常使用的是relplot()
。这是一个图形级函数,用于使用两种常用方法可视化统计关系:散点图和折线图。relplot()
将 FacetGrid
与以下两个轴级函数之一组合在一起:
scatterplot()
(和kind="scatter"
默认值)lineplot()
(和kind="line"
)
正如我们将看到的,这些函数可能非常有启发性,因为它们使用简单且易于理解的数据表示形式,但这些表示形式仍然可以表示复杂的数据集结构。它们可以这样做,因为它们绘制了二维图形,可以通过使用色调、大小和样式的语义映射最多三个附加变量来增强这些图形。
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
import seaborn as sns
sns.set_theme(style="darkgrid")
tips = sns.load_dataset("tips", data_home='seaborn-data',cache=True)
sns.relplot(data=tips, x="total_bill", y="tip")
<seaborn.axisgrid.FacetGrid at 0x7f12d710e360>
虽然点是在二维中绘制的,但可以通过根据第三个变量对点进行着色来将另一个维度添加到图中。在 seaborn 中,这被称为使用“色调语义”,因为点的颜色获得了意义:
sns.relplot(data=tips, x="total_bill", y="tip", hue="smoker")
<seaborn.axisgrid.FacetGrid at 0x7f12d6f691c0>
为了强调类之间的差异,并提高可访问性,可以对每个类使用不同的标记样式:
sns.relplot(
data=tips,
x="total_bill", y="tip", hue="smoker", style="smoker"
)
<seaborn.axisgrid.FacetGrid at 0x7f12d6f35be0>
也可以通过独立更改每个点的色调和样式来表示四个变量。但这应该小心,因为眼睛对形状的敏感度远低于对颜色的敏感度:
sns.relplot(
data=tips,
x="total_bill", y="tip", hue="smoker", style="time",
)
<seaborn.axisgrid.FacetGrid at 0x7f12ced45be0>
在上面的示例中,色调语义是分类的,因此应用了默认的定性调色板。如果色相语义为数字(具体而言,如果可以将其转换为浮点),则默认着色将切换到顺序调色板:
sns.relplot(
data=tips, x="total_bill", y="tip", hue="size",
)
<seaborn.axisgrid.FacetGrid at 0x7f12cec5c9b0>
在这两种情况下,您都可以自定义调色板。有很多选择可以做到这一点。这里,我们使用cubehelix_palette()
的字符串接口定制一个顺序调色板:
sns.relplot(
data=tips,
x="total_bill", y="tip",
hue="size", palette="ch:r=-.5,l=.75"
)
<seaborn.axisgrid.FacetGrid at 0x7f12cecedb80>
第三种语义变量改变每个点的大小:
sns.relplot(data=tips, x="total_bill", y="tip", size="size")
<seaborn.axisgrid.FacetGrid at 0x7f12cd3093d0>
与 matplotlib.pyplot.scatter()
不同,变量的文字值不用于选取点的面积。相反,以数据单位表示的值范围被规范化为以面积单位为单位的范围。此范围可以定制:
sns.relplot(
data=tips, x="total_bill", y="tip",
size="size", sizes=(15, 200)
)
<seaborn.axisgrid.FacetGrid at 0x7f12d7145b80>
dowjones = sns.load_dataset("dowjones",data_home='seaborn-data',cache=True)
sns.relplot(data=dowjones, x="Date", y="Price", kind="line")
<seaborn.axisgrid.FacetGrid at 0x7f12cd3391c0>
fmri = sns.load_dataset("fmri",data_home='seaborn-data',cache=True)
sns.relplot(data=fmri, x="timepoint", y="signal", kind="line")
<seaborn.axisgrid.FacetGrid at 0x7f12cd2f7770>
置信区间是使用引导计算的,这对于较大的数据集来说可能非常耗时。因此,可以禁用它们:
sns.relplot(
data=fmri, kind="line",
x="timepoint", y="signal", errorbar=None,
)
<seaborn.axisgrid.FacetGrid at 0x7f12cd1491c0>
另一个不错的选择,尤其是对于较大的数据,是通过绘制标准差而不是置信区间来表示每个时间点的分布分布:
sns.relplot(
data=fmri, kind="line",
x="timepoint", y="signal", errorbar="sd",
)
<seaborn.axisgrid.FacetGrid at 0x7f12cd182930>
要完全关闭聚合,将estimator
参数设置为None
。当数据在每个点上有多个观察值时,可能会产生奇怪的效果。
sns.relplot(
data=fmri, kind="line",
x="timepoint", y="signal",
estimator=None,
)
<seaborn.axisgrid.FacetGrid at 0x7f12cd03eab0>
sns.relplot(
data=fmri, kind="line",
x="timepoint", y="signal", hue="event",
)
<seaborn.axisgrid.FacetGrid at 0x7f12cd0d7740>
默认情况下,向线图添加样式语义会更改线条中的破折号模式:
sns.relplot(
data=fmri, kind="line",
x="timepoint", y="signal",
hue="region", style="event",
)
<seaborn.axisgrid.FacetGrid at 0x7f12cec6a5d0>
但是,您可以通过每个观测值中使用的标记来识别子集,可以与破折号一起识别子集,也可以代替破折号:
sns.relplot(
data=fmri, kind="line",
x="timepoint", y="signal", hue="region", style="event",
dashes=False, markers=True,
)
<seaborn.axisgrid.FacetGrid at 0x7f12cce32240>
与散点图一样,在使用多个语义制作线图时要小心。虽然有时提供信息,但它们也可能难以解析和解释。但是,即使您只检查一个附加变量的更改,更改线条的颜色和样式也很有用。这可以使绘图在打印为黑白或由色盲人员查看时更易于访问:
sns.relplot(
data=fmri, kind="line",
x="timepoint", y="signal", hue="event", style="event",
)
<seaborn.axisgrid.FacetGrid at 0x7f12ccfb7b90>
在处理重复测量数据(即,具有多次采样的单位)时,还可以单独绘制每个采样单位,而无需通过语义来区分它们。这样可以避免图例混乱:
sns.relplot(
data=fmri.query("event == 'stim'"), kind="line",
x="timepoint", y="signal", hue="region",
units="subject", estimator=None,
)
<seaborn.axisgrid.FacetGrid at 0x7f12ccd3a9c0>
lineplot()
中图例的默认颜色图和处理还取决于色调语义是分类还是数字:
dots = sns.load_dataset("dots", data_home='seaborn-data',cache=True).query("align == 'dots'")
sns.relplot(
data=dots, kind="line",
x="time", y="firing_rate",
hue="coherence", style="choice",
)
<seaborn.axisgrid.FacetGrid at 0x7f12ccd38e90>
可能会发生这样的情况,即使 hue
变量是数字,它也不能很好地用线性色阶表示。这就是这里的情况, hue
变量的级别是对数缩放的。你可以通过传递一个列表或字典来为每行提供特定的颜色值:
palette = sns.cubehelix_palette(light=.8, n_colors=6)
sns.relplot(
data=dots, kind="line",
x="time", y="firing_rate",
hue="coherence", style="choice", palette=palette,
)
<seaborn.axisgrid.FacetGrid at 0x7f12cccbdbe0>
或者,您可以更改颜色图的规范化方式:
from matplotlib.colors import LogNorm
palette = sns.cubehelix_palette(light=.7, n_colors=6)
sns.relplot(
data=dots.query("coherence > 0"), kind="line",
x="time", y="firing_rate",
hue="coherence", style="choice",
hue_norm=LogNorm(),
)
<seaborn.axisgrid.FacetGrid at 0x7f12cd0c2300>
第三个语义 size 改变了行的宽度:
sns.relplot(
data=dots, kind="line",
x="time", y="firing_rate",
size="coherence", style="choice",
)
<seaborn.axisgrid.FacetGrid at 0x7f12cce9a570>
虽然size
变量通常是数值,但也可以将分类变量与线条的宽度进行映射。这样做时要小心,因为除了“粗”线和“细”线之外,很难区分更多。但是,当线条具有高频变化时,破折号可能很难察觉,因此在这种情况下使用不同的宽度可能更有效:
sns.relplot(
data=dots, kind="line",
x="time", y="firing_rate",
hue="coherence", size="choice", palette=palette,
)
<seaborn.axisgrid.FacetGrid at 0x7f12cc9e8560>
healthexp = sns.load_dataset("healthexp", data_home='seaborn-data',cache=True).sort_values("Year")
sns.relplot(
data=healthexp, kind="line",
x="Spending_USD", y="Life_Expectancy", hue="Country",
sort=False
)
<seaborn.axisgrid.FacetGrid at 0x7f12ccce3050>
也可以沿 y 轴排序(和聚合):
sns.relplot(
data=fmri, kind="line",
x="signal", y="timepoint", hue="event",
orient="y",
)
<seaborn.axisgrid.FacetGrid at 0x7f12cc75fb90>
sns.relplot(
data=tips,
x="total_bill", y="tip", hue="smoker", col="time",
)
<seaborn.axisgrid.FacetGrid at 0x7f12cc61fb90>
还可以通过这种方式显示两个变量的影响:一个通过对列进行分面,另一个通过对行进行分面。当您开始向网格添加更多变量时,您可能希望减小图形大小。请记住,FacetGrid
的大小是由每个小平面的高度和纵横比参数化:
sns.relplot(
data=fmri, kind="line",
x="timepoint", y="signal", hue="subject",
col="region", row="event", height=3,
estimator=None
)
<seaborn.axisgrid.FacetGrid at 0x7f12cc61c8c0>
当您想要检查变量的多个级别的效果时,最好在列上对该变量进行分面,然后将分面“包装”到行中:
sns.relplot(
data=fmri.query("region == 'frontal'"), kind="line",
x="timepoint", y="signal", hue="event", style="event",
col="subject", col_wrap=5,
height=3, aspect=.75, linewidth=2.5,
)
<seaborn.axisgrid.FacetGrid at 0x7f12cc675be0>
这些可视化有时被称为“点阵图”或“小倍数图”,它们非常有效,因为它们以一种格式呈现数据,使眼睛很容易发现总体模式和偏离这些模式的情况。虽然您应该利用scatterplot()
和relplot()
提供的灵活性,但始终要记住,几个简单的图通常比一个复杂的图更有效。