数据挖掘比赛入坑(五)

EDA(Exploratory Data Analysis)

(探索性分析数据)

  • 目的:
  1. 理解每个特征的意义;
  2. 知道哪些特征是有用的,这些特征哪些是直接可以用的,哪些需要经过变换才能用,为之后的特征工程做准备

1)每个特征的意义、特征类型:

1
2
df.describe()
df['Category'].unique()

2)看是否存在missing value(特征数据是否缺失)

1
df.loc[df.Dates.isnull(),'Dates']

3)看每个特征下的数据分布,用boxplot或者hist

1
2
3
4
5
6
7
%matplotlib inline
import matplotlib.pyplot as plt
df.boxplot(column='Fare', by = 'Pclass')
plt.hist(df['Fare'], bins = 10, range =(df['Fare'].min(),df['Fare'].max()))
plt.title('Fare >distribution')
plt.xlabel('Fare')
plt.ylabel('Count of Passengers')

4)看一些特征之间的联立情况,用pandas的groupby

1
2
temp = pd.crosstab([df.Pclass, df.Sex], df.Survived.astype(bool))
temp.plot(kind='bar', stacked=True, color=['red','blue'], grid=False)

Seaborn(sns)官方文档学习笔记

艺术化的图表控制

Matplotlib无疑是高度可定制的,但快速实施出吸引人的细节就变得有些复杂。Seaborn作为一个带着定制主题和高级界面控制的Matplotlib扩展包,能让绘图变得更轻松,本部分主要介绍seaborn是如何对matplotlib输出的外观进行控制的。

1
2
3
4
5
6
%matplotlib inline
#jupyter notebook 中的魔法函数,如果不是使用该软件请使用plt.show()用于显示图像
import numpy as np
import matplotlib as mpl
import matplotlib.pyplot as plt
np.random.seed(sum(map(ord,"aesthetics"))) # 定义种子

定义一个含偏移的正弦图像,来比较传统的matplotlib和seaborn的不同:

1
2
3
4
def sinplot(flip=1):
x = np.linspace(0,14,100)
for i in range(1,7):
plt.plot(x,np.sin(x+i*.5)*(7-i)*flip)

使用matplotlib默认设置的图形效果:

1
sinplot()

要切换到seaborn默认值,只需调用set()函数。

1
2
sns.set()
sinplot()

seaborn默认的灰色网格底色灵感来源于matplotlib却更加柔和。大多数情况下,图应优于表。seaborn的默认灰色网格底色避免了刺目的干扰,对于多个方面的图形尤其有用,是一些更复杂的工具的核心。

Seaborn将matplotlib参数分成两个独立的组。第一组设定了美学风格,第二组则是不同的度量元素,这样就可以很容易地添加到代码当中了。

操作这些参数的接口是两对函数。为了控制样式,使用axes_style()和set_style()函数。为了扩展绘图,请使用plotting_context()和set_context()函数。在这两种情况下,第一个函数返回一个参数字典,第二个函数则设置matplotlib默认属性。

样式控制:axes_style() and set_style()
有5个seaborn的主题,适用于不同的应用和人群偏好:

  • darkgrid 黑色网格(默认)
  • whitegrid 白色网格
  • dark 黑色背景
  • white 白色背景
  • ticks 应该是四周都有刻度线的白背景?

网格能够帮助我们查找图表中的定量信息,而灰色网格主题中的白线能避免影响数据的表现,白色网格主题则类似的,当然更适合表达“重数据元素”(heavy data elements不理解)

1
2
3
sns.set_style("whitegrid")
data = np.random.normal(size=(20, 6)) + np.arange(6) / 2
sns.boxplot(data=data);

pic1
对于许多场景,(特别是对于像对话这样的设置,您主要想使用图形来提供数据模式的印象),网格就不那么必要了

1
2
sns.set_style("dark")
sinplot()

pic2

1
2
sns.set_style("white")
sinplot()

pic3
有时你可能想要给情节增加一点额外的结构,这就是ticks参数的用途:

1
2
3
sns.set_style("ticks")
sinplot()
# 官方的例子在上方/右方也拥有刻度线,而验证时却没有(是jupyter notebook的原因?)

pic4
特别的可以通过sns.axes_style(style=None, rc=None) 返回一个sns.set_style()可传的参数的字典

通过类似sns.set_style(“ticks”, {“xtick.major.size”: 8, “ytick.major.size”: 8})的方式写入更具体的配置样式。

关于sns.axes_style()下面会有说明和运行结果

用despine()进行边框控制
white和ticks参数的样式,都可以删除上方和右方坐标轴上不需要的边框,这在matplotlib中是无法通过参数实现的,却可以在seaborn中通过despine()函数轻松移除他们。

1
2
3
sns.set_style("white")
sinplot() # 默认无参数状态,就是删除上方和右方的边框
sns.despine()

pic5
一些图的边框可以通过数据移位,当然调用despine()也能做同样的事。当边框没有覆盖整个数据轴的范围的时候,trim参数会限制留存的边框范围。

1
2
3
f, ax = plt.subplots()
sns.violinplot(data=data)
sns.despine(offset=10, trim=True); # offset 两坐标轴离开距离;

pic6
你也可以通过往despine()中添加参数去控制边框

1
2
3
4
sns.set_style("whitegrid")
sns.boxplot(data=data, palette="deep")
sns.despine(left=True) # 删除左边边框
st = sns.axes_style("darkgrid")

pic7
despine(fig=None, ax=None, top=True, right=True, left=False, bottom=False, offset=None, trim=False)
从plot()函数中移除顶部或右边的边框

临时设定图形样式
虽然来回切换非常容易,但sns也允许用with语句中套用axes_style()达到临时设置参数的效果(仅对with块内的绘图函数起作用)。这也允许创建不同风格的坐标轴。

1
2
3
4
5
with sns.axes_style("darkgrid"):
plt.subplot(211)
sinplot()
plt.subplot(212)
sinplot(-1)

pic8
seaborn样式中最重要的元素
如果您想要定制seanborn的样式,可以将参数字典传递给axes_style()和set_style()的rc参数。注意,只能通过该方法覆盖样式定义的一部分参数。(然而,更高层次的set()函数接受任何matplotlib参数的字典)。

如果您想要查看包含哪些参数,您可以只调用该函数而不带参数,这将返回当前设置的字典:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
sns.axes_style()

{'axes.axisbelow': True,
'axes.edgecolor': 'white',
'axes.facecolor': '#EAEAF2',
'axes.grid': True,
'axes.labelcolor': '.15',
'axes.linewidth': 0.0,
'figure.facecolor': 'white',
'font.family': ['sans-serif'],
'font.sans-serif': ['Arial',
'Liberation Sans',
'Bitstream Vera Sans',
'sans-serif'],
'grid.color': 'white',
'grid.linestyle': '-',
'image.cmap': 'Greys',
'legend.frameon': False,
'legend.numpoints': 1,
'legend.scatterpoints': 1,
'lines.solid_capstyle': 'round',
'text.color': '.15',
'xtick.color': '.15',
'xtick.direction': 'out',
'xtick.major.size': 0.0,
'xtick.minor.size': 0.0,
'ytick.color': '.15',
'ytick.direction': 'out',
'ytick.major.size': 0.0,
'ytick.minor.size': 0.0}

或许,你可以试试不同种类的参数效果

1
2
sns.set_style("darkgrid", {"axes.facecolor": ".9"})
sinplot()

pic9
通过 plotting_context() 和 set_context() 调整绘图元素
另一组参数控制绘图元素的规模,这应该让您使用相同的代码来制作适合在较大或较小的情节适当的场景中使用的情节。

首先,可以通过sns.set()重置参数。

1
sns.set()

四种预设,按相对尺寸的顺序(线条越来越粗),分别是paper,notebook, talk, and poster。notebook的样式是默认的,上面的绘图都是使用默认的notebook预设。

1
2
3
sns.set_context("paper")
plt.figure(figsize=(8,6))
sinplot()

1
2
3
4
# default 默认设置
sns.set_context("notebook")
plt.figure(figsize=(8,6))
sinplot()
1
2
3
sns.set_context("talk")
plt.figure(figsize=(8,6))
sinplot()
1
2
3
sns.set_context("poster")
plt.figure(figsize=(8,6))
sinplot()

通过观察各种样式的结果,你应当可以了解context函数

类似的,还可以使用其中一个名称来调用set_context()来设置参数,您可以通过提供参数值的字典来覆盖参数。
通过更改context还可以独立地扩展字体元素的大小。(这个选项也可以通过顶级set()函数获得)。

1
2
sns.set_context("notebook", font_scale=1.5, rc={"lines.linewidth": 2.5})
sinplot()

类似地(尽管它可能用处不大),也可以使用with嵌套语句进行临时的设置。
样式和上下文都可以用set()函数快速地进行配置。这个函数还设置了默认的颜色选项,在下一节将详细介绍这一功能。

斑驳陆离的调色板

颜色显然比图形风格的其他方面都更加重要,因为颜色使用得当就可以有效显示或隐藏数据中的特征。有许多的好资源都可以了解关于在可视化中使用颜色的技巧,推荐Rob Simmon的《series of blog posts》和这篇进阶的技术文章,matplotlib文档现在也有一个很好的教程,说明了如何在内置色彩映射中构建的一些感知特性。

Seaborn让你更容易选择和使用那些适合你数据和视觉的颜色。

1
2
3
4
5
6
%matplotlib inline
import numpy as np
import seaborn as sns
import matplotlib.pyplot as plt
sns.set(rc={"figure.figsize": (6, 6)})
np.random.seed(sum(map(ord, "palettes")))

通过color_palette()创建调色板
最重要的直接设置调色板的函数就是color_palette()。这个函数提供了许多(并非所有)在seaborn内生成颜色的方式。并且它可以用于任何函数内部的palette参数设置(在某些情况下当需要多种颜色时也可以传入到color参数)

color_palette()允许任意的seaborn调色板或matplotlib的颜色映射(除了jet,你应该完全不使用它)。它还可以使用任何有效的matplotlib格式指定的颜色列表(RGB元组、十六进制颜色代码或HTML颜色名称)。返回值总是一个RGB元组的列表。

最后,直接调用没有传入参数的color_palette()将返回默认的颜色循环。

对应的函数set_palette()接受相同的参数,并为所有图设置默认的颜色循环。你也可以在with块中使用color_palette()来实现临时的更改调色板配置(下面有详细例子)。

通常在不知道数据的具体特征的情况下不可能知道什么类型的调色板或颜色映射对于一组数据来说是最好的。因此,我们将用三种不同类型的调色板:分类色板、连续色板和离散色板,来区分和使用color_palette()函数。

分类色板
分类色板(定性)是在区分没有固定顺序的数据时最好的选择。

在导入seaborn库后,默认的颜色循环被更改为一组六种颜色。虽然这些颜色可能会让你想起matplotlib的标准颜色循环,但他们无疑更赏心悦目一些。

分布数据集的可视化

在处理一组数据时,通常首先要做的是了解变量是如何分布的。这一章将简要介绍seborn中用于检查单变量和双变量分布的一些工具。你可能还想看看分类变量的章节,来看看函数的例子,这些函数让我们很容易比较变量的分布。

1
2
3
4
5
6
7
8
9
10
%matplotlib inline
import numpy as np
import pandas as pd
from scipy import stats, integrate
import matplotlib.pyplot as plt

import seaborn as sns
sns.set(color_codes=True)

np.random.seed(sum(map(ord, "distributions")))
  • 单变量分布
    最方便的方式是快速查看单变量分布无疑是使用distplot()函数。默认情况下,这将绘制一个直方图,并拟合出核密度估计(KDE)。
    1
    2
    x = np.random.normal(size=100)
    sns.distplot(x);

pic10

  • 直方图
    直方图应当是非常熟悉的函数了,在matplotlib中就存在hist函数。直方图通过在数据的范围内切成数据片段,然后绘制每个数据片段中的观察次数,来表示整体数据的分布。
    为了说明这一点,我们删除密度曲线并添加了地毯图,每个观察点绘制一个小的垂直刻度。您可以使用rugplot()函数来制作地毯图,但它也可以在distplot()中使用:
    1
    sns.distplot(x, kde=False, rug=True);

pic11
绘制直方图时,主要的选择是使用切分数据片段的数量或在何位置切分数据片段。 distplot()使用一个简单的规则来很好地猜测并给予默认的切分数量,但尝试更多或更少的数据片段可能会显示出数据中的其他特征:

1
sns.distplot(x, bins=20, kde=False, rug=True);

pic12

  • 核密度估计(KDE) Kernel density estimaton
    或许你对核密度估计可能不像直方图那么熟悉,但它是绘制分布形状的有力工具。如同直方图一样,KDE图会对一个轴上的另一轴的高度的观测密度进行描述:
    1
    sns.distplot(x, hist=False, rug=True);

pic13
绘制KDE比绘制直方图更有计算性。所发生的是,每一个观察都被一个以这个值为中心的正态( 高斯)曲线所取代。

1
2
3
4
5
6
7
8
9
10
11
12
x = np.random.normal(0, 1, size=30)
bandwidth = 1.06 * x.std() * x.size ** (-1 / 5.)
support = np.linspace(-4, 4, 200)

kernels = []
for x_i in x:

kernel = stats.norm(x_i, bandwidth).pdf(support)
kernels.append(kernel)
plt.plot(support, kernel, color="r")

sns.rugplot(x, color=".2", linewidth=3)

pic14
接下来,这些曲线可以用来计算支持网格中每个点的密度值。得到的曲线再用归一化使得它下面的面积等于1:

1
2
3
density = np.sum(kernels, axis=0)
density /= integrate.trapz(density, support)
plt.plot(support, density);

pic15
我们可以看到,如果我们在seaborn中使用kdeplot()函数,我们得到相同的曲线。 这个函数由distplot()使用,但是当您只想要密度估计时,它提供了一个更直接的界面,更容易访问其他选项:

1
sns.kdeplot(x, shade=True);

pic16
KDE的带宽bandwidth(bw)参数控制估计对数据的拟合程度,与直方图中的bin(数据切分数量参数)大小非常相似。 它对应于我们上面绘制的内核的宽度。 默认中会尝试使用通用引用规则猜测一个适合的值,但尝试更大或更小的值可能会有所帮助:

1
2
3
4
sns.kdeplot(x)
sns.kdeplot(x, bw=.2, label="bw: 0.2")
sns.kdeplot(x, bw=2, label="bw: 2")
plt.legend();

pic17
如上所述,高斯KDE过程的性质意味着估计延续了数据集中最大和最小的值。 可以通过cut参数来控制绘制曲线的极值值的距离; 然而,这只影响曲线的绘制方式,而不是曲线如何拟合:

1
2
sns.kdeplot(x, shade=True, cut=0)
sns.rugplot(x);

pic18

  • 拟合参数分布
    还可以使用distplot()将参数分布拟合到数据集,并可视化地评估其与观察数据的对应关系:
    1
    2
    x = np.random.gamma(6, size=200)
    sns.distplot(x, kde=False, fit=stats.gamma);

pic19

  • 绘制双变量分布
    在绘制两个变量的双变量分布也是有用的。在seaborn中这样做的最简单的方法就是在jointplot()函数中创建一个多面板数字,显示两个变量之间的双变量(或联合)关系以及每个变量的单变量(或边际)分布和轴。
    1
    2
    3
    mean, cov = [0, 1], [(1, .5), (.5, 1)]
    data = np.random.multivariate_normal(mean, cov, 200)
    df = pd.DataFrame(data, columns=["x", "y"])

pic20

  • 散点图
    双变量分布的最熟悉的可视化方式无疑是散点图,其中每个观察结果以x和y值表示。这是两个方面的地毯图。可以使用matplotlib中的plt.scatter函数绘制散点图,它也是jointplot()函数显示的默认方式。

    1
    sns.jointplot(x="x", y="y", data=df);
  • HexBin图
    直方图的双变量类似物被称为“hexbin”图,因为它显示了落在六边形仓内的观测数。该图适用于较大的数据集。通过matplotlib plt.hexbin函数和jointplot()中的样式可以实现。 它最好使用白色背景:

    1
    2
    3
    x, y = np.random.multivariate_normal(mean, cov, 1000).T
    with sns.axes_style("white"):
    sns.jointplot(x=x, y=y, kind="hex", color="k");

pic21

  • 核密度估计
    使用上述内核密度估计程序可视化双变量分布也是可行的。在seaborn中,这种图用等高线图显示,可以在jointplot()中作为样式传入参数使用:
    1
    sns.jointplot(x="x", y="y", data=df, kind="kde");

pic22
还可以使用kdeplot()函数绘制二维核密度图。这样可以将这种绘图绘制到一个特定的(可能已经存在的)matplotlib轴上,而jointplot()函数只能管理自己:

1
2
3
4
f, ax = plt.subplots(figsize=(6, 6))
sns.kdeplot(df.x, df.y, ax=ax)
sns.rugplot(df.x, color="g", ax=ax)
sns.rugplot(df.y, vertical=True, ax=ax);

pic23
如果是希望更连续地显示双变量密度,您可以简单地增加n_levels参数增加轮廓级数:

1
2
3
f, ax = plt.subplots(figsize=(6, 6))
cmap = sns.cubehelix_palette(as_cmap=True, dark=0, light=1, reverse=True)
sns.kdeplot(df.x, df.y, cmap=cmap, n_levels=60, shade=True);

pic24
jointplot()函数使用JointGrid来管理。为了获得更多的灵活性,您可能需要直接使用JointGrid绘制图形。jointplot()在绘制后返回JointGrid对象,您可以使用它来添加更多图层或调整可视化的其他方面:

1
2
3
4
g = sns.jointplot(x="x", y="y", data=df, kind="kde", color="m")
g.plot_joint(plt.scatter, c="w", s=30, linewidth=1, marker="+")
g.ax_joint.collections[0].set_alpha(0)
g.set_axis_labels("$X$", "$Y$");

pic25

  • 呈现数据集中成对的关系
    要在数据集中绘制多个成对双变量分布,可以使用pairplot()函数。这将创建一个轴的矩阵,并显示DataFrame中每对列的关系。默认情况下,它也绘制每个变量在对角轴上的单变量:
1
2
iris = sns.load_dataset("iris")
sns.pairplot(iris);

pic26
对于jointplot()和JointGrid之间的关系,pairplot()函数是建立在一个PairGrid对象上的,可以直接使用它来获得更大的灵活性:

1
2
3
g = sns.PairGrid(iris)
g.map_diag(sns.kdeplot)
g.map_offdiag(sns.kdeplot, cmap="Blues_d", n_levels=6);

pic27

线性关系的可视化

这章介绍的针对回归类型的散点数据的可视化可能是未来机器学习最直接的助理,这章给我的感悟很多。

许多数据集包含多个定量变量,分析的目的通常是将这些变量相互关联起来。 我们以前讨论过可以通过显示两个变量的联合分布来实现的功能。 然而,使用统计模型来估计两个噪声观测组之间的简单关系可能是非常有帮助的。 本章讨论的功能将通过线性回归的通用框架进行。

在Tukey的精神中,Seaborn的回归图主要是为了添加一个视觉指南,有助于在探索性数据分析期间强调数据集中的模式。 也就是说,Seaborn本身并不是统计分析的一揽子计划。 要获得与回归模型拟合相关的量化措施,您应该使用statsmodels。 然而,Seaborn的目标是通过可视化快速,轻松地探索数据集,使之变得与通过统计表格来探索数据集一样重要(如果不是更重要的话)。

1
2
3
4
5
6
7
8
9
10
11
12
%matplotlib inline
import numpy as np
import pandas as pd
import matplotlib as mpl
import matplotlib.pyplot as plt

import seaborn as sns
sns.set(color_codes=True)

np.random.seed(sum(map(ord, "regression")))

tips = sns.load_dataset("tips")

  • 绘制线性回归模型的函数

使用Seaborn中的两个主要功能可视化通过回归确定的线性关系。这些函数regplot()和lmplot()是密切相关的,并且共享了大部分的核心功能。然而,了解他们不同的方式很重要,以便您可以快速为特定工作选择正确的工具。

在最简单的调用中,两个函数绘制了两个变量x和y的散点图,然后拟合回归模型y〜x并绘制了该回归线的结果回归线和95%置信区间:

1
sns.regplot(x="total_bill", y="tip", data=tips);

pic28

1
sns.lmplot(x="total_bill", y="tip", data=tips);

pic29

很显然,所得到的的图的结果是相同的,除了图形形状略有些不同,这里会简短的解释。

目前,要知道的另一个主要区别是regplot()以各种格式接受x和y变量,包括numpy数组、Pandas的Series列或DataFrame对象的变量引用;不一样的是,lmplot()将数据集作为一个必需的参数,而x和y变量必须指定为字符串。这种数据格式称为“长格式”或“整洁”数据。除了这种输入灵活性,regplot()可以看做是拥有lmplot()特征的子集,所以后面将使用后者进行演示。

备注:
这里官方的例子实际上并不好,比较容易的理解方式是:上面的结果可以在regplot()函数中通过只传入x和y绘出:sns.regplot(x=tips[“total_bill”], y=tips[“tip”]);而相应的sns.lmplot(x=tips[“total_bill”], y=tips[“tip”])这种写法就会报错,因为数据集data是lmplot()的必传参数。

当其中一个变量取值为离散型的时候,可以拟合一个线性回归。然而,这种数据集生成的简单散点图通常不是最优的:

1
2
3
4
5
6
7
8
9
tips.head()

total_bill tip sex smoker day time size big_tip
0 16.99 1.01 Female No Sun Dinner 2 False
1 10.34 1.66 Male No Sun Dinner 3 True
2 21.01 3.50 Male No Sun Dinner 3 True
3 23.68 3.31 Male No Sun Dinner 2 False
4 24.59 3.61 Female No Sun Dinner 4 False
sns.lmplot(data=tips,x="size",y="tip")

pic30
个常用的方法是为离散值添加一些随机噪声的“抖动”(jitter),使得这些值的分布更加明晰。

值得注意的是,抖动仅适用于散点图数据,且不会影响拟合的回归线本身

1
sns.lmplot(x="size", y="tip", data=tips, x_jitter=.05);

pic31
另一种选择是在每个独立的数据分组中对观察结果进行折叠,以绘制中心趋势的估计以及置信区间:

1
sns.lmplot(x="size", y="tip", data=tips, x_estimator=np.mean);

pic32

  • 不同类型的模型拟合
    上面使用的简单线性回归模型非常简单,但是,它不适用于某些种类的数据集。 Anscombe's quartet数据集显示了一些简单线性回归提供了简单目视检查清楚显示差异的关系估计的例子。 例如,在第一种情况下,线性回归是一个很好的模型:
1
2
3
anscombe = sns.load_dataset("anscombe")
sns.lmplot(x="x", y="y", data=anscombe.query("dataset == 'I'"),
ci=None, scatter_kws={"s": 80});

pic33
第二个数据集中的线性关系是一样的,但是基本清楚地表明这不是一个好的模型:

1
2
sns.lmplot(x="x", y="y", data=anscombe.query("dataset == 'II'"),
ci=None, scatter_kws={"s": 80});

pic34
在存在这些高阶关系的情况下,lmplot()和regplot()可以拟合多项式回归模型来拟合数据集中的简单类型的非线性趋势:

1
2
sns.lmplot(x="x", y="y", data=anscombe.query("dataset == 'II'"),
order=2, ci=None, scatter_kws={"s": 80});

pic35
除了正在研究的主要关系之外,“异常值”观察还有一个不同的问题,它们由于某种原因而偏离了主要关系:

1
2
sns.lmplot(x="x", y="y", data=anscombe.query("dataset == 'III'"),
ci=None, scatter_kws={"s": 80});

pic36
在有异常值的情况下,它可以使用不同的损失函数来减小相对较大的残差,拟合一个健壮的回归模型,传入robust=True:

1
2
sns.lmplot(x="x", y="y", data=anscombe.query("dataset == 'III'"),
robust=True, ci=None, scatter_kws={"s": 80});

pic37
当y变量是二进制时,简单的线性回归也“工作”了,但提供了不可信的预测结果:

1
2
3
tips["big_tip"] = (tips.tip / tips.total_bill) > .15
sns.lmplot(x="total_bill", y="big_tip", data=tips,
y_jitter=.03);

pic38
在这种情况下,解决方案是拟合逻辑(Logistic)回归,使得回归线显示给定值x的y=1的估计概率:

1
2
sns.lmplot(x="total_bill", y="big_tip", data=tips,
logistic=True, y_jitter=.03);

pic39
请注意,逻辑回归估计比简单回归计算密集程度(Robust回归也是如此),并且由于使用引导程序计算回归线周围的置信区间,您可能希望将其关闭获得更快的迭代速度(使用参数ci=None)。

一个完全不同的方法是使用一个lowess smoother拟合非参数回归。 这种方法具有最少的假设,尽管它是计算密集型的,因此目前根本不计算置信区间:

1
2
sns.lmplot(x="total_bill", y="tip", data=tips,
lowess=True);

pic40
residplot()是一个有用的工具,用于检查简单的回归模型是否拟合数据集。它拟合并移除一个简单的线性回归,然后绘制每个观察值的残差值。 理想情况下,这些值应随机散布在y = 0附近:

1
2
sns.residplot(x="x", y="y", data=anscombe.query("dataset == 'I'"),
scatter_kws={"s": 80});

pic41
如果残差中有结构,则表明简单的线性回归是不合适的:

1
2
sns.residplot(x="x", y="y", data=anscombe.query("dataset == 'II'"),
scatter_kws={"s": 80});

pic42

  • 调节其他变量
    上面的图表显示了许多方法来探索一对变量之间的关系。然而,通常,一个更有趣的问题是“这两个变量之间的关系如何作为第三个变量的函数而变化?”这是regplot()和lmplot()之间的区别。 虽然regplot()总是显示单个关系,lmplot()将regplot()与FacetGrid结合在一起,提供了一个简单的界面,可以在“faceted”图上显示线性回归,从而允许您探索与多达三个其他类别变量的交互。

分类关系的最佳方式是绘制相同轴上的两个级别,并使用颜色来区分它们:

1
sns.lmplot(x="total_bill", y="tip", hue="smoker", data=tips);

pic43
除了颜色之外,还可以使用不同的散点图标记来使黑色和白色的图像更好地绘制。 您还可以完全控制所用的颜色:

1
2
sns.lmplot(x="total_bill", y="tip", hue="smoker", data=tips,
markers=["o", "x"], palette="Set1");

pic44
要添加另一个变量,您可以绘制多个“facet”,每个级别的变量出现在网格的行或列中:

1
sns.lmplot(x="total_bill", y="tip", hue="smoker", col="time", data=tips);

pic45

1
2
sns.lmplot(x="total_bill", y="tip", hue="smoker",
col="time", row="sex", data=tips);

pic46

  • 控制绘制的大小和形状
    在我们注意到由regplot()和lmplot()创建的默认绘图看起来是一样的,但在轴上却具有不同大小和形状。 这是因为func:regplot是一个“轴级”功能绘制到特定的轴上。 这意味着您可以自己制作多面板图形,并精确控制回归图的位置。 如果没有提供轴,它只需使用“当前活动的”轴,这就是为什么默认绘图与大多数其他matplotlib函数具有相同的大小和形状的原因。要控制大小,您需要自己创建一个图形对象。
    1
    2
    f, ax = plt.subplots(figsize=(5, 6))
    sns.regplot(x="total_bill", y="tip", data=tips, ax=ax);

pic47
相反,lmplot()图的大小和形状通过FacetGrid界面使用size和aspect参数进行控制,这些参数适用于每个图中的设置,而不是整体图形:

1
2
sns.lmplot(x="total_bill", y="tip", col="day", data=tips,
col_wrap=2, size=3);

pic48

1
2
sns.lmplot(x="total_bill", y="tip", col="day", data=tips,
aspect=.5);

pic49

  • 在其他背景下绘制回归
    另外一些Seaborn函数在更大,更复杂的绘制中使用regplot()。 第一个是在上一章分布介绍的jointplot()函数。 除了前面讨论的绘图样式之外,jointplot()可以使用regplot()通过传递kind =”reg”来显示关节轴上的线性回归拟合:
    1
    sns.jointplot(x="total_bill", y="tip", data=tips, kind="reg");

pic50
使用kind=”reg”的pairplot()函数结合了regplot()和PairGrid来显示数据集中变量之间的线性关系。 注意这是不同于lmplot()的。 在下图中,两轴在第三个变量的两个级别上不显示相同的关系; 相反,PairGrid()用于显示数据集中变量的不同配对之间的多个关系:

1
2
sns.pairplot(tips, x_vars=["total_bill", "size"], y_vars=["tip"],
size=5, aspect=.8, kind="reg");

pic51
类似lmplot(),但不同于jointplot(),使用hue参数在pairplot()中内置了一个附加分类变量的条件:

1
2
sns.pairplot(tips, x_vars=["total_bill", "size"], y_vars=["tip"],
hue="smoker", size=5, aspect=.8, kind="reg");

pic52

分类数据的绘制

我们之前探讨了如何使用散点图和回归模型拟合来可视化两个变量之间的关系,以及如何在其他分类变量的层次之间进行展示。 当然,还有一大类问题就是分类数据的问题了? 在这种情况下,散点图和回归模型方法将不起作用。当然,有几个观察可视化这种关系的选择,我们将在本章中讨论。

非常实用的方法是将Seaborn的分类图分为三类,将分类变量每个级别的每个观察结果显示出来,显示每个观察分布的抽象表示,以及应用统计估计显示的权重趋势和置信区间:

  • 第一个包括函数swarmplot()和stripplot()
  • 第二个包括函数boxplot()和violinplot()
  • 第三个包括函数barplot()和pointplt()

在了解他们如何接受数据传入方面,尽管每个参数都聚有控制应用于该数据可视化细节的特定参数,但这些功能都共享一个基本的API。

这与之前的regplot()和lmplot()的关系非常相似(备注:在seaborn的构架中很容易分成这样两类用途相似,使用有所差异的替代方案函数)。在Seaborn中,相对低级别和相对高级别的方法用于定制分类数据的绘制图,上面列出的函数都是低级别的,他们绘制在特定的matplotlib轴上。还有更高级别的factorplot()(备注:这是一个非常简明的快速绘制函数,具体用法会在最后有详细介绍),它将这些功能与FacetGrid结合,以便在面板的网格中应用分类图像。

使用“整洁”格式的DataFrame调用这些函数是最简单和最好的,尽管较低级别的函数也接受宽形式的DataFrames或简单的观察向量。见下面的例子。

1
2
3
4
5
6
7
8
9
10
11
12
%matplotlib inline
import numpy as np
import pandas as pd
import matplotlib as mpl
import matplotlib.pyplot as plt
import seaborn as sns
sns.set(style="whitegrid", color_codes=True)

np.random.seed(sum(map(ord, "categorical")))
titanic = sns.load_dataset("titanic")
tips = sns.load_dataset("tips")
iris = sns.load_dataset("iris")
  • 分类散点图
    显示分类变量级别中某些定量变量的值的一种简单方法使用stripplot(),它会将分散图概括为其中一个变量是分类的:
    1
    sns.stripplot(x="day", y="total_bill", data=tips);

pic53
在条纹图中,散点图通常将重叠。这使得很难看到数据的完整分布。一个简单的解决方案是使用一些随机的“抖动”调整位置(仅沿着分类轴)
备注:抖动是平时可视化中的常用的观察“密度”的方法,除了使用参数抖动,特定的抖动需求也可以用numpy在数据上处理实现

1
sns.stripplot(x="day", y="total_bill", data=tips, jitter=True);

pic54
不同的方法是使用函数swarmplot(),它使用避免重叠点的算法将分类轴上的每个散点图点定位:
备注:道理上,即使抖动还是会有重叠的可能,所以这种方法可能更好

1
sns.swarmplot(x="day", y="total_bill", data=tips);

pic55
当然也可以传入hue参数添加多个嵌套的分类变量。高于分类轴上的颜色和位置时冗余的,现在每个都提供有两个变量之一的信息:

1
sns.swarmplot(x="day", y="total_bill", hue="sex",data=tips);

pic56
一般来说,Seaborn分类绘图功能试图从数据中推断类别的顺序。 如果您的数据有一个pandas分类数据类型,那么类别的默认顺序可以在那里设置。 对于其他数据类型,字符串类型的类别将按照它们在DataFrame中显示的顺序进行绘制,但是数组类别将被排序:

1
sns.swarmplot(x="size", y="total_bill", data=tips);

pic57
使用这些图,将分类变量放在垂直轴上是非常有用的(当类别名称相对较长或有很多类别时,这一点特别有用)。 您可以使用orient关键字强制定向,但通常可以从传递给x和/或y的变量的数据类型推断绘图方向:

1
sns.swarmplot(x="total_bill", y="day", hue="time", data=tips);

pic58

  • 分类内的观测分布
    分类散点图固然简单实用,但在某些特定的的情况下,他们可以提供的值的分布信息会变得及其有限(并不明晰)。 有几种方式可以方便的解决这个问题,在类别之间进行简单比较并汇总信息,我们快速讨论并比较一些适合这类数据观测的函数。
  • 箱线图
    第一个是熟悉的boxplot()。这种图形显示了分布的三个四分位值与极值。“晶须”延伸到低于和低四分位数的1.5 IQR内的点,然后独立显示落在该范围之外的观测值。 重要的是,这意味着boxplot中的每个值的显示都对应于数据中的实际观察值:

IQR即统计学概念四分位距,第一四分位与第三四分位之间的距离,具体内容请参考更深入的相关资料

1
sns.boxplot(x="day", y="total_bill", hue="time", data=tips);

pic59

  • 提琴图
    不同的方法是一个violinplot(),它结合了箱体图和分布教程中描述的核心密度估计过程:
    备注:核密度估计,即全文中提到的,或参数内传入的kde,具体概念内容请参考相关文档
    1
    sns.violinplot(x="total_bill", y="day", hue="time", data=tips);

pic60
这种方法使用核密度估计来更好地描述值的分布。此外,小提琴内还显示了箱体四分位数和晶须值。由于小提琴使用KDE,还有一些其他可以调整的参数,相对于简单的boxplot增加了一些复杂性:

1
2
sns.violinplot(x="total_bill", y="day", hue="time", data=tips,
bw=.1, scale="count", scale_hue=False);

pic61
当色调参数只有两个级别时,也可以传入参数split至violinplot(),这样可以更有效地利用空间:

1
sns.violinplot(x="day", y="total_bill", hue="sex", data=tips, split=True);

pic62
最后,在绘制提琴图的时候有几个选项,包括显示每个人的观察结果而不是总结框图值的方法:

1
2
sns.violinplot(x="day", y="total_bill", hue="sex", data=tips,
split=True, inner="stick", palette="Set3");

pic63
将swarmplot()或者swarmplot()与violinplot()或boxplot()结合使用可以显示每个观察结果以及分布的摘要:
备注:说实话,并不推荐这么做,过多的信息除了炫技没有什么实际用处。

1
2
sns.violinplot(x="day", y="total_bill", data=tips, inner=None)
sns.swarmplot(x="day", y="total_bill", data=tips, color="w", alpha=.5);

pic64

  • 类别内的统计估计
    通常,不是显示每个类别中的分布,你可能希望显示值的集中趋势。 Seaborn有两种显示此信息的主要方法,但重要的是,这些功能的基本API与上述相同。
  • 条形图
    最熟悉的方式完成这个目标是一个条形图。 在Seaborn中barplot()函数在完整数据集上运行,并显示任意估计,默认情况下使用均值。 当在每个类别中有多个观察值时,它还使用引导来计算估计周围的置信区间,并绘制使用误差条:
    1
    sns.barplot(x="sex", y="survived", hue="class", data=titanic);

pic65
条形图的特殊情况是当您想要显示每个类别中的观察次数,而不是计算第二个变量的统计量。这类似于分类而不是定量变量的直方图。在Seaborn中,使用countplot()函数很容易绘制:

1
sns.countplot(x="deck", data=titanic, palette="Greens_d");

pic66
可以使用上面讨论的所有选项来调用barplot()和countplot(),以及在每个函数的详细文档中的其他选项:

1
sns.countplot(y="deck", hue="class", data=titanic, palette="Greens_d");

pic67

  • 点图
    pointplot()函数提供了可视化相同信息的另一种风格。该函数还对另一轴的高度估计值进行编码,而不是显示一个完整的柱型,它只绘制点估计和置信区间。另外,点图连接相同hue类别的点。这使得很容易看出主要关系如何随着第二个变量的变化而变化,因为你的眼睛很好地收集斜率的差异:
    1
    sns.pointplot(x="sex", y="survived", hue="class", data=titanic);

pic68
为了使能够在黑白中重现的图形,可以使用不同的标记和线条样式来展示不同hue类别的层次:

1
2
3
sns.pointplot(x="class", y="survived", hue="sex", data=titanic,
palette={"male": "g", "female": "m"},
markers=["^", "o"], linestyles=["-", "--"]);

pic69

  • 绘制“宽格式”数据

虽然使用“长格式”或“整洁”数据是优选的,但是这些功能也可以应用于各种格式的“宽格式”数据,包括pandas DataFrame或二维numpy数组阵列。这些对象应该直接传递给数据参数:

1
sns.boxplot(data=iris,orient="h");

pic70
此外,这些函数接受Pandas或numpy对象的向量,而不是DataFrame中的变量

1
sns.violinplot(x=iris.species, y=iris.sepal_length);

pic71
为了控制由上述功能制作的图形的大小和形状,您必须使用matplotlib命令自己设置图形。 当然,这也意味着这些图块可以和其他种类的图块一起在一个多面板的绘制中共存:

1
2
f, ax = plt.subplots(figsize=(7, 3))
sns.countplot(y="deck", data=titanic, color="c");

pic72

  • 绘制多层面板分类图
    正如我们上面提到的,有两种方法可以在Seaborn中绘制分类图。与回归图中的二元性相似,您可以使用上面介绍的函数,也可以使用更高级别的函数factorplot(),将这些函数与FacetGrid()相结合,通过这个图形的更大的结构来增加展示其他类别的能力。 默认情况下,factorplot()产生一个pairplot():
    1
    sns.factorplot(x="day", y="total_bill", hue="smoker", data=tips);

pic73

1
sns.factorplot(x="day", y="total_bill", hue="smoker", data=tips, kind="bar");

pic74
使用factorplot()的主要优点是很容易调用”facet”展开更多其他分类变量:

1
2
sns.factorplot(x="day", y="total_bill", hue="smoker",
col="time", data=tips, kind="swarm");

pic75
任何一种图形都可以画出来。基于FacetGrid的工作原理,要更改图形的大小和形状,需要指定适用于每个方面的size和aspect参数:

1
2
sns.factorplot(x="time", y="total_bill", hue="smoker",
col="day", data=tips, kind="box", size=4, aspect=.5);

pic76
重要的是要注意,你也可以直接使用boxplot()和FacetGrid来制作这个图。但是,必须特别注意确保分类变量的顺序在每个方面实施,方法是使用具有Categorical数据类型的数据或通过命令和hue_order。

1
2
3
sns.factorplot(x="time", y="total_bill", hue="smoker",hue_order=["No","Yes"]
,col="day", data=tips, kind="box", size=4, aspect=.5,
palette="Set3");

pic77
由于分类图的广义API,它们应该很容易应用于其他更复杂的上下文。 例如,它们可以轻松地与PairGrid结合,以显示多个不同变量之间的分类关系:

1
2
3
4
5
g = sns.PairGrid(tips,
x_vars=["smoker", "time", "sex"],
y_vars=["total_bill", "tip"],
aspect=.75, size=3.5)
g.map(sns.violinplot, palette="pastel");

pic78

绘制数据网格

在探索中等维度数据时,一个有用的方法是在数据集的不同子集上绘制相同绘图的多个实例。这种技术有时被称为“格子”或“格子”绘图,它与“小倍数”的想法有关。 它允许观看者快速提取大量关于复杂数据的信息。 Matplotlib可以很好地支持制作具有多个轴的图形; seaborn建立在此之上,以将结构直接链接到数据集结构上进行绘制。

要使用这些功能,您的数据必须位于Pandas DataFrame中,并且必须采用Hadley Whickam称为“整洁”数据的形式。 简而言之,这意味着您的数据框架应该被结构化,使得每一列都是一个变量,每一行都是一个观测。

对于高级使用,您可以直接使用本教程本部分中讨论的对象,这将提供最大的灵活性。一些Seaborn功能(如lmplot(),factorplot()和pairplot())也在幕后使用。与其他Seaborn功能“Axes级别”不同,并且绘制在特定(可能已经存在的)matplotlib轴上,而无需其他操作的图形,这些较高级别的功能在调用时创建一个数字,并且通常更严格地说明如何设置。在某些情况下,对于这些函数或其依赖的类的构造函数的参数将提供与图形大小不同的接口属性,如lmplot()的情况,您可以在其中设置每个方面的高度和纵横比而不是整体尺寸。使用这些对象之一的任何函数总是在绘制之后返回,而且这些对象中的大多数都具有方便的方法来改变绘制,通常以更抽象和简单的方式。

1
2
3
4
5
6
7
8
9
10
%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()在内部使用这个对象,并且当它们被修改时,它们返回该对象,以便可以用于进一步的调整。

1
2
tips = sns.load_dataset("tips")
tips.head()
1
g = sns.FacetGrid(tips, col="time")

pic79
像这样初始化网格设置了matplotlib图形和轴,但并没有绘制任何东西。

在此网格上可视化数据的主要方法是使用FacetGrid.map()方法,提供一个绘图功能和数据框中变量的名称来绘制。我们来看一下这些子集中提示的分布,使用直方图。

1
2
g = sns.FacetGrid(tips, col="time")
g.map(plt.hist, "tip");

pic80
此功能将绘制图形并注释轴,并在一个步骤中生成完成。 要做一个关系图,只需传递多个变量名。可以提供关键字参数,将其传递给绘图功能:

1
2
3
g = sns.FacetGrid(tips, col="sex", hue="smoker")
g.map(plt.scatter, "total_bill", "tip", alpha=.7)
g.add_legend();

pic81
有几个选项可以控制可以传递给类构造函数的网格的外观。

1
2
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);

pic82
请注意,matplotlib API没有正式支持margin_titles,并且在所有情况下都可能无法正常运行。 特别是,它目前不能用于图形之外的注释框。

通过提供每个图形的高度以及纵横比来达到设置图形大小的目的

1
2
g = sns.FacetGrid(tips, col="day", size=4, aspect=.5)
g.map(sns.barplot, "sex", "total_bill");

pic83
在matplotlib大于1.4的版本中,可以传递在gridspec模块中的参数,增加其尺寸来吸引注意力。当然,在每个方面可视化不同数量的组的数据集的分布时,这无疑是特别实用的。

1
2
3
4
5
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");

pic84
这里,默认的顺序来自于DataFrame中的书序。如果用于定义facets具有分类变量的类型,则会实用类别的顺序。否则,facets将按照级别的顺序排列。当然,也可以使用适当的*_ order参数来指定任何平面维度的数据顺序。

1
2
3
4
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);

pic85
可以提供任何Seaborn调色板(即可以传递给color_palette()的参数),还可以使用将色调变量中值的名称映射到有效的matplotlib颜色的字典:

1
2
3
4
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();

pic86
您还可以让色调的其他方面在色相变量的水平上有所不同,这对于绘制黑白打印时将更易于理解的图形将有所帮助。 为此,将字典传递给hue_kws,其中键是绘图函数关键字参数的名称,值是关键字值的列表,每个级别的hue对应一个变量。

1
2
3
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();

pic87
如果您有多个级别的一个变量,您可以沿着列绘制,但是”wrap”它们,以便跨越多个行。 当这样做时,将不能使用行(row)变量。

1
2
3
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);

pic88
使用FacetGrid.map()(可以多次调用)绘制图形之后,您可能需要调整绘图的某些方面。 FacetGrid对象上还有一些方法可以在更高层次的抽象上操作图形。 最通用的是FacetGrid.set(),还有其他更专门的方法,如FacetGrid.set_axis_labels(),它遵循内部方面没有轴标签的效果。 例如:

1
2
3
4
5
6
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);

pic89
对于更多的定制,您可以直接使用underling matplotlib图形和Axes对象,它们分别作为图和轴(二维数组)的成员属性存储。 当没有行或列面的图形时,还可以使用ax属性直接访问单个轴。

1
2
3
4
5
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));

pic90

  • 将自定义函数应用在网格上
    在使用FacetGrid时,并不限于现有的matplotlib和Seaborn功能。但是,要正常工作,使用必须遵循以下规则:
  1. 必须绘制在“当前活动”的matplotlib轴上。 这对matplotlib.pyplot命名空间中的函数是正确的,如果要使用其方法,可以调用plt.gca来获取对当前Axes的直接引用。
  2. 它必须接受它在位置参数中绘制的数据。 在内部,FacetGrid将传递一系列针对传递给FacetGrid.map()的命名位置参数的数据。
  3. 它必须能够接受color和label关键字参数,理想情况下它将非常有用。在大多数情况下,使用一个通用的**kwargs字典是最简单的,并将其传递给底层的绘图函数。

我们来看一下您可以绘制的功能的最简单的例子。该函数只需要给出每个方向的向量的数据:

1
2
3
4
5
6
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");

pic91
如果我们想做一个双变量图,你应该编写函数,以便它接受x轴为第一个变量和y轴为第二个变量:

1
2
3
4
5
6
7
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");

pic92
因为plt.scatter接受color和label关键字参数并正确运行,我们可以简单的再添加一个hue参数:

1
2
3
g = sns.FacetGrid(tips, hue="time", col="sex", size=4)
g.map(qqplot, "total_bill", "tip")
g.add_legend();

pic93
这种方法还允许我们使用额外的sns设置来区分hue变量的级别,依赖这些关键字的参数将使得显示摆脱对刻面变量的依赖:

1
2
3
4
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();

pic94
一些时候,将需要映射一个适合的color和label关键字参数以达到预期的效果。在这种情况下,您将会有明确地把握并熟悉处理自定义函数的逻辑。例如这种方法将允许使用映射plt.hexbin函数和那些类似的不方便使用FacetGrid API的调用:

1
2
3
4
5
6
7
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]);

pic95

  • 用PairGrid and pairplot()绘制成对的关系
    PairGrid还允许您使用相同的绘图类型快速绘制小子图的网格,以在每个图形中显示数据。在一个PairGrid中,每个行和列分配给一个不同的变量,所以生成的图显示了数据集中的每个成对关系。这种风格的绘图有时被称为“散点图矩阵”,因为这是显示每个关系的最常见方式,但是PairGrid不仅限于散点图。
    了解FacetGrid和PairGrid之间的区别很重要。在前者中,每个方面显示出与其他变量的不同级别相同的关系。在后者中,每个图都显示不同的关系(尽管上下三角形将具有镜像图)。使用PairGrid可以为您提供非常快速,非常高级的汇总数据集中有趣的关系。
    该类的基本用法与FacetGrid非常相似。首先初始化网格,然后将绘图函数传递给map方法,并在每个子图上调用它。还有一个配套功能,pairplot()交易了一些灵活性更快的绘图。
    1
    2
    3
    iris = sns.load_dataset("iris")
    g = sns.PairGrid(iris)
    g.map(plt.scatter);

pic96
可以在对角线上绘制不同的函数,以显示每列中变量的单变量分布。 请注意,轴刻度线将不对应于该图的计数或密度轴。

1
2
3
g = sns.PairGrid(iris)
g.map_diag(plt.hist)
g.map_offdiag(plt.scatter);

pic97
使用该图的非常常见的方法是通过单独的分类变量来绘制观察值。 例如,虹膜数据集对于三种不同种类的鸢尾花中的每一种进行四次测量,以便您可以看到它们如何不同。

1
2
3
4
g = sns.PairGrid(iris, hue="species")
g.map_diag(plt.hist)
g.map_offdiag(plt.scatter)
g.add_legend();

pic98
默认情况下,使用数据集中的每个数字列,但如果需要,您可以专注于特定的关系。

1
2
g = sns.PairGrid(iris, vars=["sepal_length", "sepal_width"], hue="species")
g.map(plt.scatter);

pic99
也可以在上下三角形中使用不同的功能来强调关系的不同方面。

1
2
3
4
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);

pic100
具有对角线上的身份关系的方形网格实际上只是一个特殊情况,您可以在行和列中绘制不同的变量。

1
2
3
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]);

pic101
当然,sns属性是可配置的。 例如,您可以使用不同的调色板(例如,显示色调变量的顺序),并将关键字参数传递到绘图函数中。

1
2
3
g = sns.PairGrid(tips, hue="size", palette="GnBu_d")
g.map(plt.scatter, s=50, edgecolor="white")
g.add_legend();

pic102
PairGrid是灵活的,但是要快速查看一个数据集,可以使用pairplot()更容易。 默认情况下,该功能使用散点图和直方图,但是还可以添加其他几种(目前还可以绘制对角线上的对角线和KDEs的回归图)。

1
sns.pairplot(iris, hue="species", size=2.5);

pic103

1
g = sns.pairplot(iris, hue="species", palette="Set2", diag_kind="kde", size=2.5)

pic104

-------------本文结束感谢您的阅读-------------