Seaborn(sns)官方文档学习笔记系列包括:
在探索中等维度数据时,一个有用的方法是在数据集的不同子集上绘制相同绘图的多个实例。这种技术有时被称为“格子”或“格子”绘图,它与“小倍数”的想法有关。 它允许观看者快速提取大量关于复杂数据的信息。 Matplotlib可以很好地支持制作具有多个轴的图形; seaborn建立在此之上,以将结构直接链接到数据集结构上进行绘制。
要使用这些功能,您的数据必须位于Pandas DataFrame中,并且必须采用Hadley Whickam称为“整洁”数据的形式。 简而言之,这意味着您的数据框架应该被结构化,使得每一列都是一个变量,每一行都是一个观测。
对于高级使用,您可以直接使用本教程本部分中讨论的对象,这将提供最大的灵活性。一些Seaborn功能(如lmplot(),factorplot()和pairplot())也在幕后使用。与其他Seaborn功能“Axes级别”不同,并且绘制在特定(可能已经存在的)matplotlib轴上,而无需其他操作的图形,这些较高级别的功能在调用时创建一个数字,并且通常更严格地说明如何设置。在某些情况下,对于这些函数或其依赖的类的构造函数的参数将提供与图形大小不同的接口属性,如lmplot()的情况,您可以在其中设置每个方面的高度和纵横比而不是整体尺寸。使用这些对象之一的任何函数总是在绘制之后返回,而且这些对象中的大多数都具有方便的方法来改变绘制,通常以更抽象和简单的方式。
%matplotlib inline
import numpy as np
import pandas as pd
import seaborn as sns
from scipy import stats
import matplotlib as mpl
import matplotlib.pyplot as plt
sns.set(style="ticks")
np.random.seed(sum(map(ord, "axis_grids")))
用FacetGrid子集数据
当您想要在数据集的子集内可视化变量的分布或多个变量之间的关系时,FacetGrid类很有用。 FacetGrid可以绘制最多三个维度:row,col和hue。前两者与所得轴数有明显的对应关系;将hue变量视为沿着深度轴的第三维,其中不同的级别用不同的颜色绘制。
通过使用数据框初始化FacetGrid对象和将形成网格的行,列或色调维度的变量的名称来使用该类。 这些变量应该是分类的或离散的,然后变量的每个级别的数据将用于沿该轴的小平面。 例如,假设我们要检查tips数据集中的午餐和晚餐之间的差异。
另外,lmplot()和factorplot()在内部使用这个对象,并且当它们被修改时,它们返回该对象,以便可以用于进一步的调整。
tips = sns.load_dataset("tips")
tips.head()
total_billtipsexsmokerdaytimesize016.991.01FemaleNoSunDinner 2110.341.66MaleNoSunDinner 3221.013.50MaleNoSunDinner 3323.683.31MaleNoSunDinner 2424.593.61FemaleNoSunDinner 4
g = sns.FacetGrid(tips, col="time")
像这样初始化网格设置了matplotlib图形和轴,但并没有绘制任何东西。
在此网格上可视化数据的主要方法是使用FacetGrid.map()方法,提供一个绘图功能和数据框中变量的名称来绘制。我们来看一下这些子集中提示的分布,使用直方图。
g = sns.FacetGrid(tips, col="time")
g.map(plt.hist, "tip");
此功能将绘制图形并注释轴,并在一个步骤中生成完成。 要做一个关系图,只需传递多个变量名。可以提供关键字参数,将其传递给绘图功能:
g = sns.FacetGrid(tips, col="sex", hue="smoker")
g.map(plt.scatter, "total_bill", "tip", alpha=.7)
g.add_legend();
有几个选项可以控制可以传递给类构造函数的网格的外观。
g = sns.FacetGrid(tips, row="smoker", col="time", margin_titles=True)
g.map(sns.regplot, "size", "total_bill", color=".3", fit_reg=False, x_jitter=.1);
请注意,matplotlib API没有正式支持margin_titles,并且在所有情况下都可能无法正常运行。 特别是,它目前不能用于图形之外的注释框。
通过提供每个图形的高度以及纵横比来达到设置图形大小的目的。
g = sns.FacetGrid(tips, col="day", size=4, aspect=.5)
g.map(sns.barplot, "sex", "total_bill");
在matplotlib大于1.4的版本中,可以传递在gridspec模块中的参数,增加其尺寸来吸引注意力。当然,在每个方面可视化不同数量的组的数据集的分布时,这无疑是特别实用的。
titanic = sns.load_dataset("titanic")
titanic = titanic.assign(deck=titanic.deck.astype(object)).sort_values("deck")
g = sns.FacetGrid(titanic, col="class", sharex=False,
gridspec_kws={"width_ratios": [5, 3, 3]})
g.map(sns.boxplot, "deck", "age");
这里,默认的顺序来自于DataFrame中的书序。如果用于定义facets具有分类变量的类型,则会实用类别的顺序。否则,facets将按照级别的顺序排列。当然,也可以使用适当的*_order参数来指定任何平面维度的数据顺序。
ordered_days = tips.day.value_counts().index
g = sns.FacetGrid(tips, row="day", row_order=ordered_days,
size=1.7, aspect=4,)
g.map(sns.distplot, "total_bill", hist=False, rug=True);
可以提供任何Seaborn调色板(即可以传递给color_palette()的参数),还可以使用将色调变量中值的名称映射到有效的matplotlib颜色的字典:
pal = dict(Lunch="seagreen", Dinner="gray")
g = sns.FacetGrid(tips, hue="time", palette=pal, size=5)
g.map(plt.scatter, "total_bill", "tip", s=50, alpha=.7, linewidth=.5, edgecolor="white")
g.add_legend();
您还可以让色调的其他方面在色相变量的水平上有所不同,这对于绘制黑白打印时将更易于理解的图形将有所帮助。 为此,将字典传递给hue_kws,其中键是绘图函数关键字参数的名称,值是关键字值的列表,每个级别的hue对应一个变量。
g = sns.FacetGrid(tips, hue="sex", palette="Set1", size=5, hue_kws={"marker": ["^", "v"]})
g.map(plt.scatter, "total_bill", "tip", s=100, linewidth=.5, edgecolor="white")
g.add_legend();
如果您有多个级别的一个变量,您可以沿着列绘制,但是"wrap"它们,以便跨越多个行。 当这样做时,将不能使用行(row)变量。
attend = sns.load_dataset("attention").query("subject <= 12")
g = sns.FacetGrid(attend, col="subject", col_wrap=4, size=2, ylim=(0, 10))
g.map(sns.pointplot, "solutions", "score", color=".3", ci=None);
使用FacetGrid.map()(可以多次调用)绘制图形之后,您可能需要调整绘图的某些方面。 FacetGrid对象上还有一些方法可以在更高层次的抽象上操作图形。 最通用的是FacetGrid.set(),还有其他更专门的方法,如FacetGrid.set_axis_labels(),它遵循内部方面没有轴标签的效果。 例如:
with sns.axes_style("white"):
g = sns.FacetGrid(tips, row="sex", col="smoker", margin_titles=True, size=2.5)
g.map(plt.scatter, "total_bill", "tip", color="#334488", edgecolor="white", lw=.5);
g.set_axis_labels("Total bill (US Dollars)", "Tip");
g.set(xticks=[10, 30, 50], yticks=[2, 6, 10]);
g.fig.subplots_adjust(wspace=.02, hspace=.02);
对于更多的定制,您可以直接使用underling matplotlib图形和Axes对象,它们分别作为图和轴(二维数组)的成员属性存储。 当没有行或列面的图形时,还可以使用ax属性直接访问单个轴。
g = sns.FacetGrid(tips, col="smoker", margin_titles=True, size=4)
g.map(plt.scatter, "total_bill", "tip", color="#338844", edgecolor="white", s=50, lw=1)
for ax in g.axes.flat:
ax.plot((0, 50), (0, .2 * 50), c=".2", ls="--")
g.set(xlim=(0, 60), ylim=(0, 14));
将自定义函数应用在网格上
在使用FacetGrid时,并不限于现有的matplotlib和Seaborn功能。但是,要正常工作,使用必须遵循以下规则:
- 必须绘制在“当前活动”的matplotlib轴上。 这对matplotlib.pyplot命名空间中的函数是正确的,如果要使用其方法,可以调用plt.gca来获取对当前Axes的直接引用。
- 它必须接受它在位置参数中绘制的数据。 在内部,FacetGrid将传递一系列针对传递给FacetGrid.map()的命名位置参数的数据。
- 它必须能够接受color和label关键字参数,理想情况下它将非常有用。在大多数情况下,使用一个通用的**kwargs字典是最简单的,并将其传递给底层的绘图函数。
我们来看一下您可以绘制的功能的最简单的例子。该函数只需要给出每个方向的向量的数据:
def quantile_plot(x, **kwargs):
qntls, xr = stats.probplot(x, fit=False)
plt.scatter(xr, qntls, **kwargs)
g = sns.FacetGrid(tips, col="sex", size=4)
g.map(quantile_plot, "total_bill");
如果我们想做一个双变量图,你应该编写函数,以便它接受x轴为第一个变量和y轴为第二个变量:
def qqplot(x, y, **kwargs):
_, xr = stats.probplot(x, fit=False)
_, yr = stats.probplot(y, fit=False)
plt.scatter(xr, yr, **kwargs)
g = sns.FacetGrid(tips, col="smoker", size=4)
g.map(qqplot, "total_bill", "tip");
因为plt.scatter接受color和label关键字参数并正确运行,我们可以简单的再添加一个hue参数:
g = sns.FacetGrid(tips, hue="time", col="sex", size=4)
g.map(qqplot, "total_bill", "tip")
g.add_legend();
这种方法还允许我们使用额外的sns设置来区分hue变量的级别,依赖这些关键字的参数将使得显示摆脱对刻面变量的依赖:
g = sns.FacetGrid(tips, hue="time", col="sex", size=4,
hue_kws={"marker": ["s", "D"]})
g.map(qqplot, "total_bill", "tip", s=40, edgecolor="w")
g.add_legend();
一些时候,将需要映射一个适合的color和label关键字参数以达到预期的效果。在这种情况下,您将会有明确地把握并熟悉处理自定义函数的逻辑。例如这种方法将允许使用映射plt.hexbin函数和那些类似的不方便使用FacetGrid API的调用:
def hexbin(x, y, color, **kwargs):
cmap = sns.light_palette(color, as_cmap=True)
plt.hexbin(x, y, gridsize=15, cmap=cmap, **kwargs)
with sns.axes_style("dark"):
g = sns.FacetGrid(tips, hue="time", col="time", size=4)
g.map(hexbin, "total_bill", "tip", extent=[0, 50, 0, 10]);
用PairGrid and pairplot()绘制成对的关系
PairGrid还允许您使用相同的绘图类型快速绘制小子图的网格,以在每个图形中显示数据。在一个PairGrid中,每个行和列分配给一个不同的变量,所以生成的图显示了数据集中的每个成对关系。这种风格的绘图有时被称为“散点图矩阵”,因为这是显示每个关系的最常见方式,但是PairGrid不仅限于散点图。
了解FacetGrid和PairGrid之间的区别很重要。在前者中,每个方面显示出与其他变量的不同级别相同的关系。在后者中,每个图都显示不同的关系(尽管上下三角形将具有镜像图)。使用PairGrid可以为您提供非常快速,非常高级的汇总数据集中有趣的关系。
该类的基本用法与FacetGrid非常相似。首先初始化网格,然后将绘图函数传递给map方法,并在每个子图上调用它。还有一个配套功能,pairplot()交易了一些灵活性更快的绘图。
iris = sns.load_dataset("iris")
g = sns.PairGrid(iris)
g.map(plt.scatter);
可以在对角线上绘制不同的函数,以显示每列中变量的单变量分布。 请注意,轴刻度线将不对应于该图的计数或密度轴。
g = sns.PairGrid(iris)
g.map_diag(plt.hist)
g.map_offdiag(plt.scatter);
使用该图的非常常见的方法是通过单独的分类变量来绘制观察值。 例如,虹膜数据集对于三种不同种类的鸢尾花中的每一种进行四次测量,以便您可以看到它们如何不同。
g = sns.PairGrid(iris, hue="species")
g.map_diag(plt.hist)
g.map_offdiag(plt.scatter)
g.add_legend();
默认情况下,使用数据集中的每个数字列,但如果需要,您可以专注于特定的关系。
g = sns.PairGrid(iris, vars=["sepal_length", "sepal_width"], hue="species")
g.map(plt.scatter);
也可以在上下三角形中使用不同的功能来强调关系的不同方面。
g = sns.PairGrid(iris)
g.map_upper(plt.scatter)
g.map_lower(sns.kdeplot, cmap="Blues_d")
g.map_diag(sns.kdeplot, lw=3, legend=False);
具有对角线上的身份关系的方形网格实际上只是一个特殊情况,您可以在行和列中绘制不同的变量。
g = sns.PairGrid(tips, y_vars=["tip"], x_vars=["total_bill", "size"], size=4)
g.map(sns.regplot, color=".3")
g.set(ylim=(-1, 11), yticks=[0, 5, 10]);
当然,sns属性是可配置的。 例如,您可以使用不同的调色板(例如,显示色调变量的顺序),并将关键字参数传递到绘图函数中。
g = sns.PairGrid(tips, hue="size", palette="GnBu_d")
g.map(plt.scatter, s=50, edgecolor="white")
g.add_legend();
PairGrid是灵活的,但是要快速查看一个数据集,可以使用pairplot()更容易。 默认情况下,该功能使用散点图和直方图,但是还可以添加其他几种(目前还可以绘制对角线上的对角线和KDEs的回归图)。
sns.pairplot(iris, hue="species", size=2.5);
您还可以使用关键字参数控制显示细节,并返回PairGrid实例进行进一步的调整。
g = sns.pairplot(iris, hue="species", palette="Set2", diag_kind="kde", size=2.5)