第二章:Seaborn分布图 (Distribution Plots) 第二章:Seaborn 分布图 (Distribution Plots) 引言 数据可视化是数据分析和机器学习流程中至关重要的一环。它能够帮助我们理解数据的分布、发现数据中的模式、识别异常值,并有效地向他人传达数据洞见。Seaborn,作为 Python 中基于 Matplotlib 的高级数据可视化库,提供了丰富的功能,能够轻松创建美观且信息丰富的统计图形。在本章中,我们将深入探讨 Seaborn 提供的各种分布图 (Distribution Plots),学习如何使用它们来有效地探索和呈现数据的分布特征。 分布图是用于可视化数据集中单个变量或多个变量分布情况的图形。
引言
数据可视化是数据分析和机器学习流程中至关重要的一环。它能够帮助我们理解数据的分布、发现数据中的模式、识别异常值,并有效地向他人传达数据洞见。Seaborn,作为 Python 中基于 Matplotlib 的高级数据可视化库,提供了丰富的功能,能够轻松创建美观且信息丰富的统计图形。在本章中,我们将深入探讨 Seaborn 提供的各种分布图 (Distribution Plots),学习如何使用它们来有效地探索和呈现数据的分布特征。
分布图是用于可视化数据集中单个变量或多个变量分布情况的图形。它们帮助我们理解数据值的集中趋势、离散程度、偏态、峰度等关键统计特征。Seaborn 提供的分布图种类繁多,可以满足不同数据类型和分析需求,包括直方图、核密度估计图、经验累积分布函数图、箱线图、小提琴图、条形图、计数图等等。
本章将系统地介绍 Seaborn 中常用的分布图类型,并通过代码示例详细讲解如何使用 Seaborn 函数创建和定制这些图形。我们还将深入探讨每种分布图的适用场景、解读方法以及背后的统计学原理,帮助您在实际数据分析工作中选择合适的分布图,并从中提取有价值的信息。
2.1 单变量分布图 (Univariate Distribution Plots)
单变量分布图旨在可视化单个变量的分布情况。Seaborn 提供了多种函数来绘制单变量分布图,包括 histplot(), kdeplot(), ecdfplot(), 和 rugplot()。
sns.histplot()直方图是最常见的分布图之一,它通过将数据划分为一系列的区间(bins),并统计每个区间内数据点的数量(或频率),然后用柱状图来表示这些数量。直方图可以直观地展示数据的频率分布,帮助我们了解数据的主要分布范围、峰值位置、以及是否存在偏态等特征。
代码实践:
import seaborn as sns import matplotlib.pyplot as plt # 加载示例数据集:鸢尾花数据集 iris = sns.load_dataset('iris') # 绘制花萼长度 (sepal_length) 的直方图 sns.histplot(data=iris, x="sepal_length") plt.title('花萼长度的直方图') plt.xlabel('花萼长度 (cm)') plt.ylabel('频数') plt.show()
代码详解:
import seaborn as sns 和 import matplotlib.pyplot as plt: 导入 Seaborn 和 Matplotlib 库,Seaborn 构建于 Matplotlib 之上,需要 Matplotlib 来显示图形。
iris = sns.load_dataset('iris'): 使用 sns.load_dataset() 函数加载 Seaborn 内置的鸢尾花 (iris) 数据集。这是一个经典的数据集,常用于教学和示例。
sns.histplot(data=iris, x="sepal_length"): 使用 sns.histplot() 函数绘制直方图。
data=iris: 指定使用的数据集为 iris。
x="sepal_length": 指定要绘制直方图的变量为 sepal_length(花萼长度)。
plt.title(...), plt.xlabel(...), plt.ylabel(...): 使用 Matplotlib 函数设置图表的标题和轴标签,使图表更易于理解。
plt.show(): 显示绘制的图形。
定制直方图:
sns.histplot() 函数提供了丰富的参数来定制直方图的外观和行为,例如:
bins: 指定直方图的柱子数量或柱子的边界。可以是一个整数 (柱子数量) 或一个序列 (柱子边界)。
kde: 布尔值,是否同时绘制核密度估计曲线 (Kernel Density Estimate)。默认为 False。
stat: 指定直方图的高度表示的统计量。默认为 "count" (频数),可选值包括 "frequency" (频率), "density" (密度), "probability" (概率)。
cumulative: 布尔值,是否绘制累积直方图。默认为 False。
hue: 指定分组变量,根据该变量的不同类别,用不同的颜色绘制直方图。
element: 指定直方图的元素类型。默认为 "bars" (柱状图),可选值包括 "step" (阶梯图), "poly" (多边形)。
fill: 布尔值,是否填充柱状图的颜色。默认为 True。
color: 指定柱状图的颜色。
edgecolor: 指定柱状图边缘的颜色。
linewidth: 指定柱状图边缘的线宽。
alpha: 指定柱状图的透明度 (0 到 1 之间)。
label: 为直方图添加标签,用于图例。
示例:定制直方图
# 定制直方图:指定柱子数量、添加 KDE 曲线、设置颜色和透明度 sns.histplot(data=iris, x="sepal_length", bins=20, kde=True, color="skyblue", alpha=0.7) plt.title('定制的直方图') plt.xlabel('花萼长度 (cm)') plt.ylabel('密度') plt.show()
在这个例子中,我们设置了 bins=20 将柱子数量增加到 20 个,kde=True 同时绘制了核密度估计曲线,color="skyblue" 设置柱子颜色为天蓝色,alpha=0.7 设置透明度为 0.7。
sns.kdeplot()核密度估计 (KDE) 图是一种非参数化的方法,用于估计随机变量的概率密度函数。与直方图不同,KDE 图提供了一个平滑的连续曲线,更清晰地展示数据的分布形状,尤其是在数据量较小时,KDE 图往往比直方图更稳定。
代码实践:
# 绘制花瓣宽度 (petal_width) 的核密度估计图 sns.kdeplot(data=iris, x="petal_width") plt.title('花瓣宽度的核密度估计图') plt.xlabel('花瓣宽度 (cm)') plt.ylabel('密度') plt.show()
代码详解:
sns.kdeplot() 函数的使用方式与 sns.histplot() 类似,主要参数也基本相同,例如 data, x, hue, color, alpha, label 等。
定制核密度估计图:
sns.kdeplot() 函数也提供了一些特有的参数来定制 KDE 图,例如:
bw_method: 指定带宽 (bandwidth) 的计算方法。带宽控制 KDE 曲线的平滑程度。可选值包括 "scott", "silverman", 一个数值 (手动指定带宽), 或一个可调用对象。
kernel: 指定核函数类型。核函数决定了每个数据点对密度估计的贡献形状。可选值包括 "gaussian", "linear", "polynomial", "sigmoid", "cosine", 等。
cumulative: 布尔值,是否绘制累积分布函数 (CDF)。默认为 False。
fill: 布尔值,是否填充 KDE 曲线下的区域。默认为 False。
levels: 用于绘制等高线图 (contour plot) 的密度水平,仅当绘制二维 KDE 图时有效。
thresh: 密度阈值,低于该阈值的等高线将被忽略,仅当绘制二维 KDE 图时有效。
示例:定制核密度估计图
# 定制 KDE 图:填充曲线、设置颜色、调整带宽 sns.kdeplot(data=iris, x="petal_width", fill=True, color="coral", bw_method="scott") plt.title('定制的核密度估计图') plt.xlabel('花瓣宽度 (cm)') plt.ylabel('密度') plt.show()
在这个例子中,我们设置了 fill=True 填充了 KDE 曲线下的区域,color="coral" 设置曲线颜色为珊瑚色,bw_method="scott" 使用 "scott" 方法自动计算带宽。
sns.ecdfplot()经验累积分布函数 (ECDF) 图展示了数据集中小于或等于给定值的观测值的比例。ECDF 图是单调递增的阶梯函数,它提供了数据分布的另一种视角,尤其适用于比较不同数据集的分布情况。
代码实践:
# 绘制花瓣长度 (petal_length) 的经验累积分布函数图 sns.ecdfplot(data=iris, x="petal_length") plt.title('花瓣长度的经验累积分布函数图') plt.xlabel('花瓣长度 (cm)') plt.ylabel('累积概率') plt.show()
代码详解:
sns.ecdfplot() 函数的使用方式与前述函数类似。
定制经验累积分布函数图:
sns.ecdfplot() 函数的常用定制参数包括:
complementary: 布尔值,是否绘制互补累积分布函数 (CCDF),即大于给定值的观测值的比例。默认为 False。
stat: 指定 ECDF 图的高度表示的统计量。默认为 "proportion" (比例),可选值包括 "count" (计数)。
color: 指定线条颜色。
linewidth: 指定线条宽度。
marker: 指定数据点的标记样式。
markersize: 指定数据点标记的大小。
示例:定制经验累积分布函数图
# 定制 ECDF 图:设置线条颜色、添加标记 sns.ecdfplot(data=iris, x="petal_length", color="purple", marker="o", markersize=5) plt.title('定制的经验累积分布函数图') plt.xlabel('花瓣长度 (cm)') plt.ylabel('累积概率') plt.show()
在这个例子中,我们设置了 color="purple" 设置线条颜色为紫色,marker="o" 添加圆形标记,markersize=5 设置标记大小为 5。
rugplot() 函数在轴上绘制数据集中每个观测值的刻度线,也被称为地毯图。它可以与直方图或 KDE 图结合使用,以更详细地展示数据的分布情况,尤其是在样本量较小时,rugplot 可以帮助我们看到每个数据点的具体位置。
代码实践:
# 绘制花萼宽度 (sepal_width) 的边缘分布图 sns.rugplot(data=iris, x="sepal_width") plt.title('花萼宽度的边缘分布图') plt.xlabel('花萼宽度 (cm)') plt.show()
代码详解:
sns.rugplot() 函数的使用方式与其他单变量分布图函数类似。
定制边缘分布图:
sns.rugplot() 函数的常用定制参数包括:
height: 指定刻度线的高度,取值范围在 0 到 1 之间。默认为轴高度的一小部分。
color: 指定刻度线颜色。
linewidth: 指定刻度线宽度。
alpha: 指定刻度线透明度。
示例:结合直方图和边缘分布图
# 结合直方图和边缘分布图 sns.histplot(data=iris, x="sepal_width", color="lightgreen") sns.rugplot(data=iris, x="sepal_width", color="darkgreen") plt.title('直方图和边缘分布图的结合') plt.xlabel('花萼宽度 (cm)') plt.ylabel('频数') plt.show()
在这个例子中,我们将 sns.histplot() 和 sns.rugplot() 绘制在同一个轴上,边缘分布图的刻度线显示了每个花萼宽度数据点的具体位置,更详细地补充了直方图的信息。
单变量分布图选择总结 (Mermaid 图):
图表解释:
单变量分布可视化: 总览,目标是可视化单个变量的分布。
数据分布特征: 根据需要展示的不同分布特征选择合适的图表。
频率分布: 关注数据值出现的频次,选择 直方图 (histplot)。
密度分布: 关注数据值的概率密度,选择 核密度估计图 (kdeplot)。
累积分布: 关注数据值小于等于某个值的比例,选择 经验累积分布函数图 (ecdfplot)。
显示个体数据点: 需要展示每个数据点的具体位置,可以选择 边缘分布图 (rugplot),通常与直方图或 KDE 图结合使用。
2.2 双变量分布图 (Bivariate Distribution Plots)
双变量分布图用于可视化两个变量之间的关系以及它们的联合分布情况。Seaborn 提供了多种函数来绘制双变量分布图,包括 scatterplot(), jointplot(), pairplot(), kdeplot() (二维), 和 histplot() (二维)。
sns.scatterplot()散点图是最基本的双变量分布图,它用点来表示数据集中两个变量的观测值,点的横纵坐标分别对应两个变量的值。散点图可以直观地展示两个变量之间的关系模式,例如线性关系、非线性关系、正相关、负相关、以及是否存在聚类或异常值。
代码实践:
# 绘制花萼长度 (sepal_length) 和花瓣宽度 (petal_width) 的散点图 sns.scatterplot(data=iris, x="sepal_length", y="petal_width") plt.title('花萼长度 vs 花瓣宽度的散点图') plt.xlabel('花萼长度 (cm)') plt.ylabel('花瓣宽度 (cm)') plt.show()
代码详解:
sns.scatterplot() 函数用于绘制散点图。
data=iris: 指定数据集。
x="sepal_length": 指定 x 轴变量。
y="petal_width": 指定 y 轴变量。
定制散点图:
sns.scatterplot() 函数提供了丰富的参数来定制散点图,例如:
hue: 指定分组变量,根据该变量的不同类别,用不同的颜色标记散点。
size: 指定大小变量,根据该变量的值,调整散点的大小。
style: 指定样式变量,根据该变量的不同类别,使用不同的形状标记散点。
alpha: 指定散点的透明度。
marker: 指定散点的形状。
sizes: 当使用 size 参数时,可以使用 sizes 参数指定大小变量的取值范围与散点大小的映射关系。
palette: 指定颜色调色板,用于 hue 参数分组的颜色。
示例:定制散点图
# 定制散点图:按物种 (species) 分组,用颜色和形状标记 sns.scatterplot(data=iris, x="sepal_length", y="petal_width", hue="species", style="species", s=80) plt.title('按物种分组的散点图') plt.xlabel('花萼长度 (cm)') plt.ylabel('花瓣宽度 (cm)') plt.legend(title='物种') plt.show()
在这个例子中,我们使用 hue="species" 和 style="species" 参数,根据鸢尾花的物种 (species) 对散点进行分组,不同物种用不同的颜色和形状标记。 s=80 设置散点的大小。 plt.legend(title='物种') 添加图例。
sns.jointplot()sns.jointplot() 函数将两个变量的散点图与它们各自的边缘分布图 (通常是直方图或 KDE 图) 组合在一起,形成一个联合分布图。这种图表可以同时展示两个变量之间的关系以及它们各自的分布情况,提供更全面的信息。
代码实践:
# 绘制花萼长度 (sepal_length) 和花瓣宽度 (petal_width) 的联合分布图 (默认散点图 + 直方图) sns.jointplot(data=iris, x="sepal_length", y="petal_width") plt.suptitle('联合分布图 (散点图 + 直方图)', y=1.02) # 使用 suptitle 设置总标题 plt.show()
代码详解:
sns.jointplot() 函数的参数与 sns.scatterplot() 类似,主要的参数是 data, x, y。
定制联合分布图:
sns.jointplot() 函数的关键定制参数是 kind,它指定了中间散点图和边缘分布图的类型。可选的 kind 值包括:
"scatter": 默认值,中间是散点图,边缘是直方图。
"kde": 中间是二维核密度估计图 (等高线图),边缘是一维 KDE 图。
"hist": 中间是二维直方图,边缘是一维直方图。
"hex": 中间是六边形箱图 (hexbin plot),边缘是直方图。
"reg": 中间是散点图,并添加线性回归线,边缘是直方图。
"resid": 中间是残差图 (residual plot),边缘是直方图。
示例:不同类型的联合分布图
# 联合分布图:kind="kde" (二维 KDE + 一维 KDE) sns.jointplot(data=iris, x="sepal_length", y="petal_width", kind="kde", fill=True, cmap="Blues") plt.suptitle('联合分布图 (二维 KDE + 一维 KDE)', y=1.02) plt.show() # 联合分布图:kind="hex" (六边形箱图 + 直方图) sns.jointplot(data=iris, x="sepal_length", y="petal_width", kind="hex", cmap="Greens") plt.suptitle('联合分布图 (六边形箱图 + 直方图)', y=1.02) plt.show()
这些例子展示了使用 kind 参数选择不同类型的联合分布图,并使用 fill=True 和 cmap 参数定制 KDE 图的填充和颜色映射。
sns.pairplot()sns.pairplot() 函数用于绘制数据集中多个变量之间所有成对关系的散点图矩阵。对于数据集中的每两个变量,pairplot() 会绘制一个散点图,并将所有这些散点图排列成一个矩阵。对角线上通常会绘制单变量的分布图 (例如直方图或 KDE 图)。pairplot() 可以快速帮助我们概览数据集中多个变量之间的关系模式。
代码实践:
# 绘制鸢尾花数据集的成对关系图 (默认散点图矩阵 + 对角线直方图) sns.pairplot(data=iris) plt.suptitle('鸢尾花数据集的成对关系图', y=1.02) plt.show()
代码详解:
sns.pairplot() 函数只需要指定 data 参数即可绘制成对关系图。
定制成对关系图:
sns.pairplot() 函数的常用定制参数包括:
hue: 指定分组变量,根据该变量的不同类别,用不同的颜色标记散点。
kind: 指定非对角线散点图的类型,默认为 "scatter",可选值包括 "scatter" 和 "kde"。
diag_kind: 指定对角线单变量分布图的类型,默认为 "hist",可选值包括 "hist" 和 "kde"。
palette: 指定颜色调色板,用于 hue 参数分组的颜色。
markers: 指定标记样式,用于 hue 参数分组的标记。
corner: 布尔值,是否只显示矩阵的下三角部分,默认为 False。
示例:定制成对关系图
# 定制成对关系图:按物种分组,对角线绘制 KDE 图,非对角线绘制 KDE 图 sns.pairplot(data=iris, hue="species", diag_kind="kde", kind="kde", palette="husl") plt.suptitle('定制的成对关系图', y=1.02) plt.show()
在这个例子中,我们使用 hue="species" 按物种分组,diag_kind="kde" 在对角线上绘制 KDE 图,kind="kde" 在非对角线上也绘制 KDE 图,palette="husl" 使用 "husl" 颜色调色板。
sns.kdeplot() (二维)sns.kdeplot() 函数也可以绘制二维核密度估计图,用于可视化两个变量的联合密度分布。二维 KDE 图通常使用等高线 (contour lines) 来表示密度水平,类似于地理地图上的等高线。
代码实践:
# 绘制花萼长度 (sepal_length) 和花瓣宽度 (petal_width) 的二维核密度估计图 sns.kdeplot(data=iris, x="sepal_length", y="petal_width", fill=True, cmap="viridis") plt.title('二维核密度估计图') plt.xlabel('花萼长度 (cm)') plt.ylabel('花瓣宽度 (cm)') plt.show()
代码详解:
绘制二维 KDE 图时,需要同时指定 x 和 y 参数。 fill=True 填充等高线之间的区域, cmap="viridis" 使用 "viridis" 颜色映射。
定制二维核密度估计图:
二维 KDE 图的一些特有定制参数包括:
levels: 指定等高线的密度水平数量或具体的密度水平值序列。
thresh: 密度阈值,低于该阈值的等高线将被忽略。
cmap: 指定颜色映射,用于填充等高线之间的区域。
colors: 指定等高线的颜色,可以使用颜色列表或颜色映射。
linewidths: 指定等高线的线宽。
linestyles: 指定等高线的线型。
示例:定制二维核密度估计图
# 定制二维 KDE 图:设置等高线数量、颜色映射 sns.kdeplot(data=iris, x="sepal_length", y="petal_width", levels=10, cmap="magma") plt.title('定制的二维核密度估计图') plt.xlabel('花萼长度 (cm)') plt.ylabel('花瓣宽度 (cm)') plt.show()
在这个例子中,我们设置了 levels=10 将等高线数量设置为 10 条,cmap="magma" 使用 "magma" 颜色映射。
sns.histplot() (二维)sns.histplot() 函数也可以绘制二维直方图,通过将二维平面划分为网格,统计每个网格单元内数据点的数量,然后用颜色深浅或柱状高度来表示数量。六边形箱图 (hexbin plot) 是二维直方图的一种变体,它使用六边形网格代替矩形网格,可以更好地近似圆形分布,并减少网格效应。
代码实践:
# 绘制花萼长度 (sepal_length) 和花瓣宽度 (petal_width) 的二维直方图 sns.histplot(data=iris, x="sepal_length", y="petal_width", cmap="Blues") plt.title('二维直方图') plt.xlabel('花萼长度 (cm)') plt.ylabel('花瓣宽度 (cm)') plt.show() # 绘制花萼长度 (sepal_length) 和花瓣宽度 (petal_width) 的六边形箱图 sns.histplot(data=iris, x="sepal_length", y="petal_width", cmap="Greens", binwidth=(0.2, 0.1), cbar=True) plt.title('六边形箱图') plt.xlabel('花萼长度 (cm)') plt.ylabel('花瓣宽度 (cm)') plt.show()
代码详解:
绘制二维直方图或六边形箱图时,同样需要同时指定 x 和 y 参数。 cmap 参数设置颜色映射。 对于六边形箱图,可以使用 binwidth 参数控制六边形箱的大小, cbar=True 显示颜色条。
定制二维直方图/六边形箱图:
二维直方图和六边形箱图的定制参数与一维直方图类似,例如 bins, binwidth, cmap, cbar, cbar_kws, thresh 等。