文章详情

短信预约-IT技能 免费直播动态提醒

请输入下面的图形验证码

提交验证

短信预约提醒成功

如何用 Python 快速揭示数据之间的各种关系

2024-12-03 18:06

关注

[[349740]]

Pandas 是 Python 中最常用的数据分析库。Python 提供了大量用于数据可视化的库,Matplotlib 是最常用的,它提供了对绘图的完全控制,并使得绘图自定义变得容易。

但是,Matplotlib 缺少了对 Pandas 的支持。而 Seaborn 弥补了这一缺陷,它是建立在 Matplotlib 之上并与 Pandas 紧密集成的数据可视化库。

然而,Seaborn 虽然活干得漂亮,但是函数众多,让人不知道到底该怎么使用它们?不要怂,本文就是为了理清这点,让你快速掌握这款利器。

这篇文章主要涵盖如下内容,

谁适合阅读这篇文章?

如果你具备 Matplotlib 和 Pandas 的基本知识,并且想探索一下 Seaborn,那么这篇文章正是不错的起点。

如果目前只掌握 Python,建议翻阅文末相关文章,特别是在掌握 Pandas 的基本使用之后再回到这里来或许会更好一些。

一、Matplotlib

尽管仅使用最简单的功能就可以完成许多任务,但是了解 Matplotlib 的基础非常重要,其原因有两个,

这里对 Matplotlib 的基础作个简单概述。下图显示了 Matplotlib 窗口的各个要素。

需要了解的三个主要的类是图形(Figure),图轴(Axes)以及坐标轴(Axis)。

本帖子中的每个示例均假设已经加载所需的模块以及数据集,如下所示,

  1. import pandas as pd 
  2. import numpy as np 
  3. from matplotlib import pyplot as plt 
  4. import seaborn as sns 
  5.  
  6. tips = sns.load_dataset('tips') 
  7. iris = sns.load_dataset('iris') 
  1. import matplotlib 
  2. matplotlib.style.use('ggplot') 
  1. tips.head() 

  1. iris.head() 

让我们通过一个例子来理解一下 Figure 和 Axes 这两个类。

  1. dates = ['1981-01-01', '1981-01-02', '1981-01-03', '1981-01-04', '1981-01-05', 
  2.          '1981-01-06', '1981-01-07', '1981-01-08', '1981-01-09', '1981-01-10'] 
  3.  
  4. min_temperature = [20.7, 17.9, 18.8, 14.6, 15.8, 15.8, 15.8, 17.4, 21.8, 20.0] 
  5. max_temperature = [34.7, 28.9, 31.8, 25.6, 28.8, 21.8, 22.8, 28.4, 30.8, 32.0] 
  6.  
  7. fig, axes = plt.subplots(nrows=1ncols=1figsize=(10,5)); 
  8. axes.plot(dates, min_temperature, label='Min Temperature'); 
  9. axes.plot(dates, max_temperature, label = 'Max Temperature'); 
  10. axes.legend(); 

plt.subplots() 创建一个 Figure 对象实例,以及 nrows x ncols 个 Axes 实例,并返回创建的 Figure 对象和 Axes 实例。在上面的示例中,由于我们传递了 nrows = 1 和 ncols = 1,因此它仅创建一个 Axes 实例。如果 nrows > 1 或 ncols > 1,则将创建一个 Axes 网格并将其返回为 nrows 行 ncols 列的 numpy 数组。

Axes 类最常用的自定义方法有,

  1. Axes.set_xlabel()         Axes.set_ylabel() 
  2. Axes.set_xlim()           Axes.set_ylim() 
  3. Axes.set_xticks()         Axes.set_yticks() 
  4. Axes.set_xticklabels()    Axes.set_yticklabels() 
  5. Axes.set_title() 
  6. Axes.tick_params() 

下面是一个使用上述某些方法进行自定义的例子,

  1. fontsize =20 
  2. fig, axes = plt.subplots(nrows=1ncols=1figsize=(15,7)) 
  3. axes.plot(dates, min_temperature, label='Min Temperature'
  4. axes.plot(dates, max_temperature, label='Max Temperature'
  5.  
  6. axes.set_xlabel('Date', fontsizefontsize=fontsize) 
  7. axes.set_ylabel('Temperature', fontsizefontsize=fontsize) 
  8.  
  9. axes.set_title('Daily Min and Max Temperature', fontsizefontsize=fontsize) 
  10.  
  11. axes.set_xticks(dates) 
  12. axes.set_xticklabels(dates) 
  13. axes.tick_params('x', labelsize=fontsizelabelrotation=30size=15
  14.  
  15.  
  16. axes.set_ylim(10,40) 
  17. axes.set_yticks(np.arange(10,41,2)) 
  18. axes.tick_params('y',labelsize=fontsize
  19.  
  20. axes.legend(fontsizefontsize=fontsize,loc='upper left'bbox_to_anchor=(1,1)); 

上面我们快速了解了下 Matplotlib 的基础知识,现在让我们进入 Seaborn。

二、Seaborn

Seaborn 中的每个绘图函数既是图形级函数又是图轴级函数,因此有必要了解这两者之间的区别。

我们可以这么来理解这一点,图形级函数可以调用不同的图轴级函数在不同的图轴上绘制不同类型的子图。

  1. sns.set_style('darkgrid') 

1. 图轴级函数

下面罗列的是 Seaborn 中所有图轴级函数的详细列表。

关系图 Relational Plots:

类别图 Categorical Plots:

分布图 Distribution Plots:

回归图 Regression Plots:

矩阵图 MatrixPlots( ):

使用任何图轴级函数需要了解的两点,

(1) 将输入数据提供给图轴级函数的不同方法

a. 列表、数组或系列

将数据传递到图轴级函数的最常用方法是使用迭代器,例如列表 list,数组 array 或序列 series

  1. total_bill = tips['total_bill'].values 
  2. tip = tips['tip'].values 
  3.  
  4. fig = plt.figure(figsize=(10, 5)) 
  5. sns.scatterplot(total_bill, tip, s=15); 

  1. tip = tips['tip'].values 
  2. day = tips['day'].values 
  3.  
  4. fig = plt.figure(figsize=(10, 5)) 
  5. sns.boxplot(day, tip, palette="Set2"); 

b. 使用 Pandas 的 Dataframe 类型以及列名。

Seaborn 受欢迎的主要原因之一是它可以直接可以与 Pandas 的 Dataframes 配合使用。在这种数据传递方法中,列名应传递给 x 和 y 参数,而 Dataframe 应传递给 data 参数。

  1. fig = plt.figure(figsize=(10, 5)) 
  2. sns.scatterplot(x='total_bill'y='tip'data=tipss=50); 

  1. fig = plt.figure(figsize=(10, 5)) 
  2. sns.boxplot(x='day'y='tip'data=tips); 

c. 仅传递 Dataframe

在这种数据传递方式中,仅将 Dataframe 传递给 data 参数。数据集中的每个数字列都将使用此方法绘制。此方法只能与以下轴级函数一起使用,

使用上述图轴级函数来展示某个数据集中的多个数值型变量的分布,是这种数据传递方式的常见用例。

  1. fig = plt.figure(figsize=(10, 5)) 
  2. sns.boxplot(data=iris); 

(2) 指定用于绘图的图轴

Seaborn 中的每个图轴级函数都带有一个 ax 参数。传递给 ax 参数的 Axes 将负责具体绘图。这为控制使用具体图轴进行绘图提供了极大的灵活性。例如,假设要查看总账单 bill 和小费 tip 之间的关系(使用散点图)以及它们的分布(使用箱形图),我们希望在同一个图形但在不同图轴上展示它们。

  1. fig, axes = plt.subplots(1, 2, figsize=(10, 7)) 
  2. sns.scatterplot(x='total_bill'y='tip'data=tipsax=axes[1]); 
  3. sns.boxplot(data = tips[['total_bill','tip']], ax=axes[0]); 

每个图轴级函数还会返回实际在其上进行绘图的图轴。如果将图轴传递给了 ax 参数,则将返回该图轴对象。然后可以使用不同的方法(如Axes.set_xlabel( ),Axes.set_ylabel( ) 等)对返回的图轴对象进行进一步自定义设置。

如果没有图轴传递给 ax 参数,则 Seaborn 将使用当前(活动)图轴来进行绘制。

  1. fig, curr_axes = plt.subplots() 
  2. scatter_plot_axes = sns.scatterplot(x='total_bill'y='tip'data=tips
  3. id(curr_axes) == id(scatter_plot_axes) 

True

在上面的示例中,即使我们没有将 curr_axes(当前活动图轴)显式传递给 ax 参数,但 Seaborn 仍然使用它进行了绘制,因为它是当前的活动图轴。id(curr_axes) == id(scatter_plot_axes) 返回 True,表示它们是相同的轴。

如果没有将图轴传递给 ax 参数并且没有当前活动图轴对象,那么 Seaborn 将创建一个新的图轴对象以进行绘制,然后返回该图轴对象。

Seaborn 中的图轴级函数并没有参数用来控制图形的尺寸。但是,由于我们可以指定要使用哪个图轴进行绘图,因此可以通过为 ax 参数传递图轴来控制图形尺寸,如下所示。

  1. fig, axes = plt.subplots(1, 1, figsize=(10, 5)) 
  2. sns.scatterplot(x='total_bill'y='tip'data=tipsax=axes); 

2. 图形级函数

在浏览多维数据集时,数据可视化的最常见用例之一就是针对各个数据子集绘制同一类图的多个实例。

Seaborn 中的图形级函数就是为这种情形量身定制的。

(1) FacetGrid

考虑下面的用例,我们想可视化不同数据子集上的总账单和小费之间的关系(通过散点图)。数据的每个子集均按以下变量的值的唯一组合进行分类,

如下所示,我们可以用 Matplotlib 和 Seaborn 轻松完成这个操作,

  1. row_variable = 'day' 
  2. col_variable = 'smoker' 
  3. hue_variable = 'sex' 
  4. row_variables = tips[row_variable].unique() 
  5. col_variables = tips[col_variable].unique() 
  6. num_rows = row_variables.shape[0] 
  7. num_cols = col_variables.shape[0] 
  8.  
  9. fig,axes = plt.subplots(num_rows, num_cols, sharex=Truesharey=Truefigsize=(15,10)) 
  10. subset = tips.groupby([row_variable,col_variable]) 
  11. for row in range(num_rows): 
  12.     for col in range(num_cols): 
  13.         ax = axes[row][col] 
  14.         row_id = row_variables[row] 
  15.         col_id = col_variables[col] 
  16.         ax_data = subset.get_group((row_id, col_id)) 
  17.         sns.scatterplot(x='total_bill'y='tip'data=ax_datahue=hue_variable,axax=ax); 
  18.         title = row_variable + ' : '  + row_id + ' | ' + col_variable + ' : ' + col_id 
  19.         ax.set_title(title); 

分析一下,上面的代码可以分为三个步骤,

在 Seaborn 中,可以将上面三部曲进一步简化为两部曲。

使用 FacetGrid,我们可以创建图轴并结合 row,col 和 hue 参数将数据集划分为三个维度。一旦创建好 FacetGrid 后,可以将具体的绘图函数作为参数传递给 FacetGrid.map( ) 以在所有图轴上绘制相同类型的图。在绘图时,我们还需要传递用于绘图的 Dataframe 中的具体列名。

  1. facet_grid = sns.FacetGrid(row='day'col='smoker'hue='sex'data=tipsheight=2aspect=2.5) 
  2. facet_grid.map(sns.scatterplot, 'total_bill', 'tip') 
  3. facet_grid.add_legend(); 

Matplotlib 为使用多个图轴绘图提供了良好的支持,而 Seaborn 在它基础上将图的结构与数据集的结构直接连接起来了。

使用 FacetGrid,我们既不必为每个数据子集显式地创建图轴,也不必显式地将数据划分为子集。这些任务由 FacetGrid( ) 和 FacetGrid.map( ) 分别在内部完成了。

我们可以将不同的图轴级函数传递给 FacetGrid.map( )。

另外,Seaborn 提供了三个图形级函数(高级接口),这些函数在底层使用 FacetGrid( ) 和 FacetGrid.map( )。

上面的图形级函数都使用 FacetGrid( ) 创建多个图轴 Axes,并用参数 kind 记录一个图轴级函数,然后在内部将该参数传递给 FacetGrid.map( )。上述三个函数分别使用不同的图轴级函数来实现不同的绘制。

  1. relplot() - FacetGrid() + lineplot()   / scatterplot()  
  2. catplot() - FacetGrid() + stripplot()  / swarmplot()   / boxplot()  
  3.                           boxenplot()  / violinplot()  / pointplot()  
  4.                           barplot()    / countplot()  
  5. lmplot()  - FacetGrid() + regplot() 

与直接使用诸如 relplot( )、catplot( ) 或 lmplot( ) 之类的高级接口相比,显式地使用 FacetGrid 提供了更大的灵活性。例如,使用 FacetGrid( ),我们还可以将自定义函数传递给 FacetGrid.map( ),但是对于高级接口,我们只能使用内置的图轴级函数指定给参数 kind。如果你不需要这种灵活性,则可以直接使用这些高级接口函数。

  1. grid = sns.relplot(x='total_bill'y='tip'row='day'col='smoker'hue='sex'data=tipskind='scatter'height=3aspect=2.0) 

  1. sns.catplot(col='day'kind='box'data=tipsx='sex'y='total_bill'hue='smoker'height=6aspect=0.5) 

  1. sns.lmplot(col='day'data=tipsx='total_bill'y='tip'hue='sex'height=6aspect=0.5) 

(2) PairGrid

PairGrid 用于绘制数据集中变量之间的成对关系。每个子图显示一对变量之间的关系。考虑以下用例,我们希望可视化每对变量之间的关系(通过散点图)。虽然可以在 Matplotlib 中也能完成此操作,但如果用 Seaborn 就会变得更加便捷。

  1. iris = sns.load_dataset('iris') 
  2. g = sns.PairGrid(iris) 

此处的实现主要分为两步,

第 1 步可以使用 PairGrid( ) 来完成。第 2 步可以使用 PairGrid.map( )来完成。

因此,PairGrid( ) 为每对变量创建图轴,而 PairGrid.map( ) 使用与该对变量相对应的数据在每个图轴上绘制曲线。我们可以将不同的图轴级函数传递给 PairGrid.map( )。

  1. grid = sns.PairGrid(iris) 
  2. grid.map(sns.scatterplot) 

  1. grid = sns.PairGrid(iris, diag_sharey=Truedespine=False
  2. grid.map_lower(sns.scatterplot) 
  3. grid.map_diag(sns.kdeplot) 

  1. grid = sns.PairGrid(iris, hue='species'
  2. grid.map_diag(sns.distplot) 
  3. grid.map_offdiag(sns.scatterplot) 

该图不必是正方形的:可以使用单独的变量来定义行和列,

  1. x_vars = ['sepal_length', 'sepal_width', 'petal_length', 'petal_width'] 
  2. y_vars = ['sepal_length'] 
  3. grid = sns.PairGrid(iris, hue='species'x_varsx_vars=x_vars, y_varsy_vars=y_vars, height=3
  4. grid.map_offdiag(sns.scatterplot, s=150
  5. # grid.map_diag(sns.kdeplot) 
  6. grid.add_legend() 

(3) JointGrid

当我们要在同一图中绘制双变量联合分布和边际分布时,使用 JointGrid。可以使用 scatter plot、regplot 或 kdeplot 可视化两个变量的联合分布。变量的边际分布可以通过直方图和/或 kde 图可视化。

  1. grid = sns.JointGrid(x="total_bill"y="tip"data=tipsheight=8
  2. grid.plot(sns.regplot, sns.distplot); 

  1. grid = sns.JointGrid(x="total_bill"y="tip"data=tipsheight=8
  2. gridgrid = grid.plot_joint(plt.scatter, color=".5"edgecolor="white"
  3. gridgrid = grid.plot_marginals(sns.distplot, kde=Truecolor=".5"

  1. g = sns.JointGrid(x="total_bill"y="tip"data=tipsheight=8
  2. gg = g.plot_joint(plt.scatter, color="g"marker='$\clubsuit$'edgecolor="white"alpha=.6) 
  3. _ = g.ax_marg_x.hist(tips["total_bill"], color="b"alpha=.36, 
  4.                       bins=np.arange(0, 60, 5)) 
  5. _ = g.ax_marg_y.hist(tips["tip"], color="r"alpha=.36, 
  6.                      orientation="horizontal"
  7.                      bins=np.arange(0, 12, 1)) 

添加带有统计信息的注释(Annotation),该注释汇总了双变量关系,

  1. from scipy import stats 
  2. g = sns.JointGrid(x="total_bill"y="tip"data=tipsheight=8
  3. gg = g.plot_joint(plt.scatter, color="b"alpha=0.36, s=40edgecolor="white"
  4. gg = g.plot_marginals(sns.distplot, kde=Falsecolor="g"
  5.  
  6. rsquare = lambda a, b: stats.pearsonr(a, b)[0] ** 2 
  7. gg = g.annotate(rsquare, template="{stat}: {val:.2f}"stat="$R^2$"loc="upper left"fontsize=12

3. 小结

探索性数据分析(EDA)涉及两个基本步骤,

Seaborn 与 Pandas 的集成有助于以最少的代码制作复杂的多维图,

 

来源:机器学习与数学内容投诉

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

软考中级精品资料免费领

  • 历年真题答案解析
  • 备考技巧名师总结
  • 高频考点精准押题
  • 2024年上半年信息系统项目管理师第二批次真题及答案解析(完整版)

    难度     813人已做
    查看
  • 【考后总结】2024年5月26日信息系统项目管理师第2批次考情分析

    难度     354人已做
    查看
  • 【考后总结】2024年5月25日信息系统项目管理师第1批次考情分析

    难度     318人已做
    查看
  • 2024年上半年软考高项第一、二批次真题考点汇总(完整版)

    难度     435人已做
    查看
  • 2024年上半年系统架构设计师考试综合知识真题

    难度     224人已做
    查看

相关文章

发现更多好内容

猜你喜欢

AI推送时光机
位置:首页-资讯-后端开发
咦!没有更多了?去看看其它编程学习网 内容吧
首页课程
资料下载
问答资讯