在关系图教程中,我们了解了如何使用不同的视觉表示来显示数据集中多个变量之间的关系。 在示例中,我们重点关注主要关系在两个数值变量之间的情况。 如果其中一个主要变量是“分类”(分为离散组),则使用更专业的可视化方法可能会有所帮助。
在seaborn中,有多种不同的方式来展示包含了分类数据的变量关系。
正如 relplot()
和 scatterplot()
/ lineplot()
之间的关系一样,
可以使用 catplot()
函数来描述分类数据,也可以使用更多坐标轴级别的绘图函数来完成这些任务。
catplot()
提供了对这些 axes-level
的函数的整合,将他们放在了一个更高级别的统一的接口之中。
将分类可视化图形分为三类,并且之后会详细探讨他们:
1.分类散点图:
stripplot()
(和默认值kind="strip"
)swarmplot()
(和kind="swarm"
)
2.分类分布图:
boxplot()
(和kind="box"
)violinplot()
(和kind="violin"
)boxenplot()
(和kind="boxen"
)
3.分类估计图:
pointplot()
(和kind="point"
)barplot()
(和kind="bar"
)countplot()
(和kind="count"
)
这些分类使用不同的粒度级别来表示数据。在决定使用哪个时,必须考虑要回答的问题。 统一的 API 可以在不同类型之间轻松切换,并从多个角度查看数据。
在本教程中,将主要关注图形级界面catplot()
。
请记住,这个函数是上面每个函数的高级接口,因此将在显示每种类型的图形时引用它们,
同时保留更详细的特定于类型的API文档。
分类散点图
catplot()
中数据的默认表示使用散点图。在seaborn中有两种不同的分类散点图,
分别以不同的方式处理了这个问题。
catplot()
使用的默认方式是 stripplot()
,它给这些散点增加了一些随机的偏移量:
import seaborn as sns
sns.set_theme()
tips = sns.load_dataset("tips", data_home='seaborn-data',cache=True)
sns.catplot(data=tips, x="day", y="total_bill")
<seaborn.axisgrid.FacetGrid at 0x7fcb76325f40>
jitter
参数控制偏移量的大小或完全禁用它:
sns.catplot(data=tips, x="day", y="total_bill", jitter=False)
<seaborn.axisgrid.FacetGrid at 0x7fcb76303b00>
第二种方法是使用算法避免了散点之间的重合。
它可以更好地表示观测值的分布,尽管它只适用于相对较小的数据集。
这种类型的图有时被称为“蜂群图”,在seaborn中用swarmplot()
绘制或者通过在catplot()
中设置 kind="swarm"
来激活:
sns.catplot(data=tips, x="day", y="total_bill", kind="swarm")
<seaborn.axisgrid.FacetGrid at 0x7fcb6e174800>
与关系图( relplot()
)类似,可以通过使用hue
参数来添加另一个维度。
(分类图目前不支持size
或style
)。每个不同的分类绘图函数处理hue
参数的方式不同。
对于散点图,只需要改变点的颜色:
sns.catplot(data=tips, x="day", y="total_bill", hue="sex", kind="swarm")
<seaborn.axisgrid.FacetGrid at 0x7fcb6e0091f0>
与数值数据不同的是,如何沿着分类变量的轴对其级别进行排序并不总是很明显的。
一般来说,固有的分类绘图函数试图从数据中推断类别的顺序。
如果数据具有pandas的Categorical
数据类型,则可以在那里设置类别的默认顺序。
如果传递给分类轴的变量看起来是数字(比如1,2,3…),则将对级别进行排序。
但是即使我们使用数字作为不同分类的标签,
它们仍然是被当做分类型数据按顺序绘制在分类变量对应的坐标轴上的:
sns.catplot(data=tips.query("size != 3"), x="size", y="total_bill")
<seaborn.axisgrid.FacetGrid at 0x7fcb6e0082c0>
从v0.13.0开始,所有分类绘图函数都有一个native_scale
参数,
当想在不改变底层数据属性的情况下使用数字或日期数据进行分类分组时,
可以将其设置为True
:
sns.catplot(data=tips.query("size != 3"), x="size", y="total_bill", native_scale=True)
<seaborn.axisgrid.FacetGrid at 0x7fcb6e0180e0>
选择默认排序的另一种选择是在数据集中显示分类的级别。
还可以使用order
参数在特定于 plot
的基础上控制排序。
当在同一张图中绘制多个分类图时,这一点很重要,我们将在下面看到更多:
sns.catplot(data=tips, x="smoker", y="tip", order=["No", "Yes"])
<seaborn.axisgrid.FacetGrid at 0x7fcb6e1498e0>
我们提到了“分类坐标轴”的概念。在这些示例中,它始终与水平轴相对应。 但是,将分类变量放在垂直轴上通常会更有帮助(尤其是当类别名称相对较长或类别较多时)。 为此,请将变量的赋值交换到轴:
sns.catplot(data=tips, x="total_bill", y="day", hue="time", kind="swarm")
<seaborn.axisgrid.FacetGrid at 0x7fcb6e01a450>
sns.catplot(data=tips, x="day", y="total_bill", kind="box")
<seaborn.axisgrid.FacetGrid at 0x7fcb6dfa38c0>
当添加hue
参数时,每一级语义变量的方框变窄,并沿着分类轴移动:
sns.catplot(data=tips, x="day", y="total_bill", hue="smoker", kind="box")
<seaborn.axisgrid.FacetGrid at 0x7fcb6dff1280>
这种行为被称为“闪避”,它由dodge
参数控制。
默认情况下(从v0.13.0开始),元素只有在重叠时才会闪避:
tips["weekend"] = tips["day"].isin(["Sat", "Sun"])
sns.catplot(data=tips, x="day", y="total_bill", hue="weekend", kind="box")
<seaborn.axisgrid.FacetGrid at 0x7fcb6e0cdf40>
一个相关的函数boxenplot()
绘制了一个类似于箱形图的图,
但对其进行了优化,以显示有关分布形状的更多信息。它最适合于较大的数据集:
diamonds = sns.load_dataset("diamonds", data_home='seaborn-data',cache=True)
sns.catplot(
data=diamonds.sort_values("color"),
x="color", y="price", kind="boxen",
)
<seaborn.axisgrid.FacetGrid at 0x7fcb6dd0b9e0>
sns.catplot(
data=tips, x="total_bill", y="day", hue="sex", kind="violin",
)
<seaborn.axisgrid.FacetGrid at 0x7fcb6dc19e80>
此方法使用核密度估计值来提供更丰富的值分布描述。 此外,箱线图中的分位数和须线也都在小提琴图中有所体现。 缺点是,由于小提琴图使用了 KDE,因此还有一些其他参数可能需要调整,相对于简单的箱线图,增加了一些复杂性:
sns.catplot(
data=tips, x="total_bill", y="day", hue="sex",
kind="violin", bw_adjust=.5, cut=0,
)
<seaborn.axisgrid.FacetGrid at 0x7fcb6db633e0>
也可以“拆分”小提琴,这样可以更有效地利用空间:
sns.catplot(
data=tips, x="day", y="total_bill", hue="sex",
kind="violin", split=True,
)
<seaborn.axisgrid.FacetGrid at 0x7fcb6da187a0>
最后,在小提琴内部绘制的绘图有几个选项,包括显示每个单独观测值而不是汇总箱线图值的方法:
sns.catplot(
data=tips, x="day", y="total_bill", hue="sex",
kind="violin", inner="stick", split=True, palette="pastel",
)
<seaborn.axisgrid.FacetGrid at 0x7fcb6da88140>
将swarmplot()
或stripplot()
与箱线图或小提琴图结合起来,
可以同时看到每个观察结果以及分布的摘要:
g = sns.catplot(data=tips, x="day", y="total_bill", kind="violin", inner=None)
sns.swarmplot(data=tips, x="day", y="total_bill", color="k", size=3, ax=g.ax)
<Axes: xlabel='day', ylabel='total_bill'>
titanic = sns.load_dataset("titanic",data_home='seaborn-data',cache=True)
sns.catplot(data=titanic, x="sex", y="survived", hue="class", kind="bar")
<seaborn.axisgrid.FacetGrid at 0x7fcb6d71ce90>
默认误差线显示 95% 置信区间,但(从 v0.12)可以从许多其他表示形式中进行选择:
sns.catplot(data=titanic, x="age", y="deck", errorbar=("pi", 95), kind="bar")
<seaborn.axisgrid.FacetGrid at 0x7fcb6da8ae40>
条形图的一个特殊情况是,当想要显示每个类别中的观测值数,而不是计算第二个变量的统计量时。
这类似于分类变量(而非定量变量)上的直方图。在 seaborn
中,使用以下功能做到这一点:
sns.catplot(data=titanic, x="deck", kind="count")
<seaborn.axisgrid.FacetGrid at 0x7fcb6d789010>
barplot()
和countplot()
在调用的时候支持所有我们在上边讨论过的选项(参数),
同时一些额外支持的参数在它们各自的详细文档中可以找到:
sns.catplot(
data=titanic, y="deck", hue="class", kind="count",
palette="pastel", edgecolor=".6",
)
<seaborn.axisgrid.FacetGrid at 0x7fcb6d9e7dd0>
sns.catplot(data=titanic, x="sex", y="survived", hue="class", kind="point")
<seaborn.axisgrid.FacetGrid at 0x7fcb6d689310>
虽然分类绘图函数没有 style
参数,但是同样可以修改线条和点的样式,
使得图片更有可读性,甚至可以在黑白色调下表现分类信息(考虑到色盲读者时,黑白色调会很有帮助):
sns.catplot(
data=titanic, x="class", y="survived", hue="sex",
palette={"male": "g", "female": "m"},
markers=["^", "o"], linestyles=["-", "--"],
kind="point"
)
<seaborn.axisgrid.FacetGrid at 0x7fcb6daafa70>
sns.catplot(
data=tips, x="day", y="total_bill", hue="smoker",
kind="swarm", col="time", aspect=.7,
)
<seaborn.axisgrid.FacetGrid at 0x7fcb6db7e330>
为了进一步定制绘图,可以使用它返回的FacetGrid
对象上的方法:
g = sns.catplot(
data=titanic,
x="fare", y="embark_town", row="class",
kind="box", orient="h",
sharex=False, margin_titles=True,
height=1.5, aspect=4,
)
g.set(xlabel="Fare", ylabel="")
g.set_titles(row_template="{row_name} class")
for ax in g.axes.flat:
ax.xaxis.set_major_formatter('${x:.0f}')