文章目录(Table of Contents)
Seaborn 介绍
之前我们学习了 Matplotlib 的一些内容(Python数据处理之 Matplotlib 学习),但是使用 Matplotlib 调整出非常漂亮的效果时,往往会伤透脑筋,非常麻烦。
Seaborn 基于 Matplotlib 核心库进行了更高级的 API 封装,可以让你轻松地画出更漂亮的图形。而 Seaborn 的漂亮主要体现在配色更加舒服、以及图形元素的样式更加细腻。
Seaborn 的安装
- pip install seaborn
如果上述命令无法安装,可以使用下面的命令进行安装
- sudo pip install git+https://github.com/mwaskom/seaborn.git
如果想要使得 seaborn 可以正常显示中文,可以在 sns.set() 的时候直接指定字体。
- sns.set(font='SimHei') # 解决Seaborn中文显示问题
Seaborn 基础
使用 Seaborn 的样式
使用seaborn来优化图像操作起来是很方便的。下面我们来对比一下优化前和优化后。
- x = np.linspace(0, 1,100)
- fig = plt.figure()
- ax = fig.add_subplot(1,1,1)
- ax.set_title(u'This is Title')
- # 四个参数分别表示x,y轴数据,'b--'表示颜色是蓝色样式是虚线,最后一个表示标签,支持LaTex
- ax.plot(x, x ** 2, 'b.', label=r'$y = x^{2}$')
- # 自动生成图例
- ax.legend()
- # 设置图像x,y轴的范围,都是从0-1
- ax.axis([0, 1, 0, 1])
- fig.show()
下面我们来进行优化。优化的方式也是很简单的,只需要使用下面两步:
- import seaborn as sns # 导入 seaborn 模块
- sns.set()
下面看一下完整的代码:
- import seaborn as sns # 导入 seaborn 模块
- sns.set()
- x = np.linspace(0, 1,100)
- fig = plt.figure()
- ax = fig.add_subplot(1,1,1)
- ax.set_title(u'This is Title')
- # 四个参数分别表示x,y轴数据,'b--'表示颜色是蓝色样式是虚线,最后一个表示标签,支持LaTex
- ax.plot(x, x ** 2, 'b.', label=r'$y = x^{2}$')
- # 自动生成图例
- ax.legend()
- # 设置图像x,y轴的范围,都是从0-1
- ax.axis([0, 1, 0, 1])
- fig.show()
可以看到背景变成了浅灰色的网格,字体也稍微做了调整。我们在上面的sns.set()
使用了默认的参数,分别如下:
- sns.set(context='notebook', style='darkgrid', palette='deep', font='sans-serif', font_scale=1, color_codes=False, rc=None)
其中:
- context='' 参数控制着默认的画幅大小,分别有 {paper, notebook, talk, poster} 四个值。其中,poster > talk > notebook > paper。
- style='' 参数控制默认样式,分别有 {darkgrid, whitegrid, dark, white, ticks}
- palette='' 参数为预设的调色板。分别有 {deep, muted, bright, pastel, dark, colorblind} 等。
- 剩下的 font='' 用于设置字体,font_scale= 设置字体大小,color_codes= 不使用调色板而采用先前的 'r' 等色彩缩写。
在这里我就不一一去演示了。
使用 Seaborn 绘制子图
我们可以使用 Seaborn 结合 matplotlib 来绘制子图。为了绘制子图,我们只需要在 sns 的 ax 中进行指定,指定子图即可。
- import seaborn as sns
- import matplotlib.pyplot as plt
- flights = sns.load_dataset("flights")
- flights_wide = flights.pivot("year", "month", "passengers")
- fig, axs = plt.subplots(2, 1, figsize=(10, 4*2), facecolor='w', edgecolor='k', sharex=True)
- # 绘制第一个子图
- sns.lineplot(data=flights_wide["Jan"], ax=axs[0], label='Jan')
- sns.lineplot(data=flights_wide["Feb"], ax=axs[0], label='Feb')
- # 绘制第二个子图
- sns.lineplot(data=flights_wide["Mar"], ax=axs[1], label='Mar')
- sns.lineplot(data=flights_wide["Apr"], ax=axs[1], label='Apr')
- sns.lineplot(data=flights_wide["May"], ax=axs[1], label='May')
- plt.show()
最终的效果如下所示:
使用 Seaborn 自定义 label
我们有的时候使用 seaborn 需要自定义 x-label 和 y-label。在 seaborn 中会返回 axis-object,接着对 axis-object 进行自定义即可。下面是一个例子:
- import pandas as pd
- import seaborn as sns
- import matplotlib.pyplot as plt
- fake = pd.DataFrame({'cat': ['red', 'green', 'blue'], 'val': [1, 2, 3]})
- ax = sns.barplot(x = 'val', y = 'cat',
- data = fake,
- color = 'black')
- ax.set(xlabel='common xlabel', ylabel='common ylabel')
- plt.show()
结果如下图所示,可以看到我们 x 和 y 上面的 label 分别被修改成了 common xlabel
和 common ylabel
。
使用 label 自定义 ticklable
我们继续完善上面的例子,我们希望对 xticklabel 和 yticklabel 进行自定义。例如自定义内容,和旋转角度。于是我们只需要加上下面两行即可:
- ax.set_xticklabels([0.0, 0.5, 1.0, 1.5, 2.0, 2.5, 3.0], rotation=-45, va="center")
- ax.set_yticklabels(['Label1', 'Label2', 'Label3'], rotation=45, va="center")
下面是最终输出的结果:
下面是完整的代码,相比上面,只是添加了两行(也就是 ax.set_xticklabel
和 ax.set_yticklabel
):
- import pandas as pd
- import seaborn as sns
- import matplotlib.pyplot as plt
- fake = pd.DataFrame({'cat': ['red', 'green', 'blue'], 'val': [1, 2, 3]})
- ax = sns.barplot(x = 'val', y = 'cat',
- data = fake,
- color = 'black')
- ax.set(xlabel='common xlabel', ylabel='common ylabel')
- ax.set_xticklabels([0.0, 0.5, 1.0, 1.5, 2.0, 2.5, 3.0], rotation=-45, va="center")
- ax.set_yticklabels(['Label1', 'Label2', 'Label3'], rotation=45, va="center")
- plt.show()
我们还可以进一步对 tick label 进行设置,下面是一个例子。关于详细的例子,可以查看 Rotating axis labels in matplotlib and seaborn。
- graph.set_xticklabels(
- graph.get_xticklabels(),
- rotation=45,
- horizontalalignment='right',
- fontweight='light',
- fontsize='x-large'
- )
Seaborn 自定义图片边框
我们可以指定图的「内边距」和「子图内的空间」,从而使得图像不会显示不完全。
- plt.subplots_adjust(wspace=0.6, hspace=0.6, left=0.1, bottom=0.22, right=0.96, top=0.96)
但是,另一个问题是如何在 subplot_adjust 中指定上述参数的值,那么答案是使用 subplot_tool 。 在显示绘图之前放置以下代码,然后会出现一个弹出窗口,您可以使用这些值并找到您喜欢的值。
- plt.subplot_tool()
我们加入上面一行代码后运行,如下图所示。可以看到会出现一个交互框,我们可以在里面调整图的「内边距」和「子图内的空间」,并且可以非常直观的显示在图像中。
使用 Seaborn 绘制基础图像
绘制线形图
我们使用 lineplot 来绘制折线图。下面放一个简单的例子,具体的用法可以查看官方文档。现在我们生成如下的测试数据:
- x = np.arange(-3, 3, 0.05)
- y1 = x
- y2 = x ** 2
- y3 = np.sin(x)
- data = pd.DataFrame(np.array([y1, y2, y3]).T, columns=['x', 'x^2', 'sin(x)'], index=x)
生成的样例数据如下所示:
- sns.lineplot(data=data)
- plt.show()
柱状图
我们可以利用 barchat 来绘制柱状图,同时使用 axhline 来绘制水平线。下面是参考代码:
- #Importing the necessary libraries
- import seaborn as sns
- import matplotlib.pyplot as plt
- #Loading the dataset into the variable 'dataset'
- dataset = sns.load_dataset("iris")
- dataset.head()
- #Graph is created and stored in the variable 'graph'
- graph = sns.barplot(x="sepal_width",y="petal_width",data=dataset)
- #Drawing a horizontal line at point 1.25
- graph.axhline(1.25)
- #The plot is shown
- plt.show()
运行上面的代码,我们可以获得以下的结果。可以看到其中包含着「柱状图」和「水平线」。
我们可以更进一步,对「水平线」添加一些样式,和 label,然后使用 legend 来进行显示。
- graph.axhline(1.25, linestyle='dashed', label="horizontal")
- plt.legend()
参考资料:Adding a horizontal line in a Seaborn plot in Python
seaborn.lmplot-二维散点图+拟合
seaborn.lmplot()
是一个非常有用的方法,它会在绘制二维散点图时,自动完成回归拟合。在sns中, 我们使用regplot也是可以完成拟合的, 但是Implot这个方法更加高级一些. 我们用官方文档里的话来说明一下.
This function combines regplot()
and FacetGrid
. It is intended as a convenient interface to fit regression models across conditional subsets of a dataset.
- import numpy as np
- import pandas as pd
- from pandas import Series,DataFrame
- # 载入绘图模块
- import matplotlib.pyplot as plt
- import seaborn as sns
- # 创建数据
- data_x = np.arange(1,100,2)
- data_y = 2*data_x+np.random.normal(10,30,len(data_x))
- data = DataFrame({'x': data_x, 'y': data_y})
- # 绘图
- sns.lmplot(x='x', y='y',data=data)
- plt.show()
除了上面的基础的使用之外, 我们还是可以设置图像的长宽比例, 同时对多组数据进行回归. 我们下面看一个简单的例子.
其中:- hue可以表示不同的label
- aspect表示绘制结果的长宽比例
- data_x = np.arange(1, 100, 2)
- data_y = 2*data_x+np.random.normal(10,30,len(data_x))
- data_label = np.random.randint(low=0,high=2,size=50)
- data = pd.DataFrame({'x':data_x, 'y':data_y, 'label':data_label})
- temp = data[data['label']==1]['x'].values
- data.loc[data['label']==1,'x'] = temp*2 + np.random.normal(10,30,len(temp))
- # 绘图
- sns.lmplot(x='x', y='y', hue='label', data=data, aspect=1.5)
- plt.show()
seaborn.PairGrid
seaborn.PairGrid()
可以用来查看两个维度数据之间的关系,用处当然也非常多了。比如,方便我们在数据分析过程中找出强关联特征。
- import numpy as np
- import pandas as pd
- from pandas import Series,DataFrame
- # 载入绘图模块
- import matplotlib.pyplot as plt
- import seaborn as sns
- # 创建数据
- data_1 = np.arange(1,100,2)
- data_2 = 2*data_x+np.random.normal(10,30,len(data_1))
- data_3 = np.random.random(len(data_1))
- col = np.random.choice(['1a','2b','3c'],len(data_1)) #这个用来分类
- data = DataFrame({'x': data_1, 'y': data_2,'z':data_3,'col':col})
- # 绘图
- sns.PairGrid(data=data).map(plt.scatter)
- plt.show()
可以看到自动将3个维度的数值进行两两配对,绘制出9张散点图,并且我们还可以加上颜色,按照分类来绘制
- import numpy as np
- import pandas as pd
- from pandas import Series,DataFrame
- # 载入绘图模块
- import matplotlib.pyplot as plt
- import seaborn as sns
- # 创建数据
- data_1 = np.arange(1,100,2)
- data_2 = 2*data_x+np.random.normal(10,30,len(data_1))
- data_3 = np.random.random(len(data_1))
- col = np.random.choice(['1a','2b','3c'],len(data_1)) #这个用来分类
- data = DataFrame({'x': data_1, 'y': data_2,'z':data_3,'col':col})
- # 绘图
- sns.PairGrid(data=data,hue='col').map(plt.scatter)
- plt.show()
seaborn.distplot
绘制关于数据的分布. 下面是从两个正态分布抽样, 并绘制出分布. 首先产生数据.- # p(x)
- mu_target = 3.5
- sigma_target = 1
- p_x = [np.random.normal(mu_target, sigma_target) for _ in range(3000)]
- # q(x)
- mu_appro = 3
- sigma_appro = 1
- q_x = [np.random.normal(mu_appro, sigma_appro) for _ in range(3000)]
- fig = plt.figure(figsize=(10,6))
- ax = fig.add_subplot(1,1,1)
- # 画出两个分布的图像
- sns.distplot(p_x, label="distribution $p(x)$")
- sns.distplot(q_x, label="distribution $q(x)$")
- plt.title("Distributions", size=16)
- plt.legend()
seaborn.PairGrid
最后我们来看一下绘制单变量和双变量的组合个图。这部分可以参考以下的链接,Seaborn JointGrid 说明文档。
- import numpy as np
- import pandas as pd
- from pandas import Series,DataFrame
- # 载入绘图模块
- import matplotlib.pyplot as plt
- import seaborn as sns
- # 创建数据
- data_x = np.arange(1,100,2)+np.random.normal(5,20,50)
- data_y = 2*data_x+np.random.normal(10,30,len(data_x))
- data = DataFrame({'x': data_x, 'y': data_y})
- # 绘图
- sns.JointGrid(x='x', y='y',data=data).plot(sns.regplot,sns.distplot)
- plt.show()
代码最后的 sns.JointGrid().plot()
用于设置图形的样式,在这里我们将双变量设置为散点图,而上面和右边的单变量设置为直方图,于是就可以得到下面的效果了。
除了上面的方式外,我们还可以通过指定「ax」的方式来绘制,如下面的例子所示:
- g = sns.JointGrid()
- # 导入数据
- penguins = sns.load_dataset("penguins")
- x, y = penguins["bill_length_mm"], penguins["bill_depth_mm"]
- # 绘制图像
- sns.scatterplot(x=x, y=y, ax=g.ax_joint)
- sns.lineplot([0, 60], [0, 20], linewidth=1, ax=g.ax_joint) # 绘制直线
- sns.histplot(x=x, fill=False, linewidth=2, ax=g.ax_marg_x)
- sns.kdeplot(y=y, linewidth=2, ax=g.ax_marg_y)
结果如下图所示,我们还在图中添加了一条直线(通过上面第九行,在 seaborn 的图中填了一个直线,也就是图中的虚线):
- 微信公众号
- 关注微信公众号
- QQ群
- 我们的QQ群号
评论