Skip to content

seaborn

虽然 Matplotlib 已经证明了自己绝对是一款超级实用且流行的数据可视化工具,但是即使骨灰粉也不得不承认它不支持的功能还有很多。 Matplotlib 的三条主要“罪状”总结如下。

  • Matplotlib 2.0 之前版本的默认配置样式绝对不是用户的最佳选择。 之前的默认样式还是仿照 1999 年前后的 MATLAB,却一直在使用。

  • Matplotlib 的 API 比较底层。虽然可以实现复杂的统计数据可视化,但是通常都需要写大量的样板代码(boilerplate code)。

  • 由于 Matplotlib 比 Pandas 早十几年,因此它并不是为 Pandas 的 DataFrame 设计的。为了实现 Pandas 的 DataFrame 数据的可视化,你必须先提取每个 Series,然后通常还需要将它们合并成适当的格式。如果有一个画图程序库可以智能地使用 DataFrame 的标签画图,那一定会很棒。

这些问题的终结者就是 Seaborn(http://seaborn.pydata.org)。Seaborn 在 Matplotlib 的基础上开发了一套 API,为默认的图形样式和颜色设置提供了理智的选择,为常用的统计图形定义了许多简单的高级函数,并与 Pandas DataFrame 的功能有机结合。

说实话,Matplotlib 团队也一直在努力解决这些问题:现在 Matplotlib 中 不仅增加了 plt.style 工具,而且与 Pandas 数 据也可以无缝衔接。Matplotlib 2.0 版已经带有对之前样式优化过的样式 表。但是即使 Matplotlib 已经有了这些进步,Seaborn 仍然是一款非常 好用的附加组件。

Seaborn 与 Matplotlib

下面用 Matplotlib 的经典图形样式和配色方案画一个简易的随机游走(random-walk)图:

python
import matplotlib.pyplot as plt

plt.style.use('classic')
import numpy as np

# 创建一些数据
rng = np.random.RandomState(0)
x = np.linspace(0, 10, 500)
y = np.cumsum(rng.randn(500, 6), 0)
# 用 Matplotlib 默认样式画图
plt.plot(x, y)
plt.legend('ABCDEF', ncol=2, loc='upper left')
plt.show()

现在尝试用 Seaborn 来实现。我们会发现,Seaborn 不仅有许多高级的画图功能,而且可以改写 Matplotlib 的默认参数,从而用简单的 Matplotlib 脚本获得更好的效果。可以用 Seaborn 的 set() 方法设置样式。为简便起见,将 Seaborn 导入简记为 sns:

python
import seaborn as sns

sns.set_style()
# 同样的画图代码!
plt.plot(x, y)
plt.legend('ABCDEF', ncol=2, loc='upper left')
plt.show()

Seaborn 图形介绍

Seaborn 的主要思想是用高级命令为统计数据探索和统计模型拟合创建各种图形。

下面将介绍一些 Seaborn 中的数据集和图形类型。虽然所有这些图形都可以用 Matplotlib 命令实现(其实 Matplotlib 就是 Seaborn 的底层),但是用 Seaborn API 会更方便。

频次直方图、KDE 核密度图

在进行统计数据可视化时,我们通常想要的就是频次直方图和多变量的联合分布图。在 Matplotlib 里面我们已经见过,相对比较简单:

python
import matplotlib.pyplot as plt
import seaborn as sns
import numpy as np
import pandas as pd

data = np.random.multivariate_normal([0, 0], [[5, 2], [2, 2]], size=2000)
data = pd.DataFrame(data, columns=['x', 'y'])
sns.set()
plt.hist(data['x'], density=True, alpha=0.5)
plt.hist(data['y'], density=True, alpha=0.5)
plt.show()

除了频次直方图,我们还可以用 KDE 获取变量分布的平滑估计。 Seaborn 通过 sns.kdeplot 实现

python
# 平滑估计
for col in 'xy':
    sns.kdeplot(data[col], shade=True)

sns.distplot(data['x'])
sns.distplot(data['y'])

如果向 kdeplot 输入的是二维数据集,那么就可以获得一个二维数据可视化图

python
sns.kdeplot(data.x, data.y)

用 sns.jointplot 可以同时看到两个变量的联合分布与单变量的独立分布。在这个图形中,使用白色背景

python
with sns.axes_style('white'):
    # sns.jointplot("x", "y", data, kind='kde')
    # 六边型
    sns.jointplot("x", "y", data, kind='hex')
plt.show()

可以向 jointplot 函数传递一些参数。例如,可以用六边形块代替频次直方图

矩阵图

当你需要对多维数据集进行可视化时,最终都要使用矩阵图(pair plot)。如果想画出所有变量中任意两个变量之间的图形,用矩阵图探索多维数据不同维度间的相关性非常有效。

下面将用著名的鸢尾花数据集来演示,其中有三种鸢尾花的花瓣与花萼数据。可视化样本中多个维度的关系非常简单,直接用 sns.pairplot 即可

python
import matplotlib.pyplot as plt
import seaborn as sns
import numpy as np
import pandas as pd

sns.set()
iris = pd.read_csv('./seaborn-data/iris.csv')
print(iris.head())

sns.pairplot(iris, hue='species', size=2.5)
plt.show()

分面频次直方图

有时观察数据最好的方法就是借助数据子集的频次直方图。 Seaborn 的 FacetGrid 函数让这件事变得非常简单。来看看某个餐厅统计的服务员收取小费的数据

python
import matplotlib.pyplot as plt
import seaborn as sns
import numpy as np
import pandas as pd

sns.set()
tips = pd.read_csv('./seaborn-data/tips.csv')
print(tips.head())
tips['tip_pct'] = 100 * tips['tip'] / tips['total_bill']

grid = sns.FacetGrid(tips, row="sex", col="time", margin_titles=True)
grid.map(plt.hist, "tip_pct", bins=np.linspace(0, 40, 15))
plt.show()

因子图

因子图(factor plot)也是对数据子集进行可视化的方法。你可以通过它观察一个参数在另一个参数间隔中的分布情况

python
with sns.axes_style(style='ticks'):
    g = sns.factorplot("day", "total_bill", "sex", data=tips, kind="box")
    g.set_axis_labels("Day", "Total Bill")
plt.show()

联合分布

与前面介绍的矩阵图类似,可以用 sns.jointplot 画出不同数据集的联合分布和各数据本身的分布

python
import matplotlib.pyplot as plt
import pandas as pd
import seaborn as sns

sns.set()
tips = pd.read_csv('./seaborn-data/tips.csv')
print(tips.head())
tips['tip_pct'] = 100 * tips['tip'] / tips['total_bill']

with sns.axes_style('white'):
    sns.jointplot("total_bill", "tip", data=tips, kind='hex')

# 联合分布图也可以自动进行 KDE 和回归
sns.jointplot("total_bill", "tip", data=tips, kind='reg')
plt.show()

条形图

时间序列数据可以用 sns.factorplot 画出条形图。用行星数据来演示:

附录

seaborn 数据集: https://github.com/mwaskom/seaborn-data