5种基本数据可视化图表:优劣分析与Matplotlib代码实现指南
[id_1298809909]

参与:刘晓坤、思源
数据可视化是数据科学家工作的重要组成部分。在项目的起始阶段,我们一般需要开展探索性数据分析,以获取对数据的洞察。利用数据可视化能够使这个过程变得更为清晰且易于理解,特别是在应对大规模、高维度的数据集时。我们在本文中介绍了 5 种最基本的数据可视化图表。接着展示了它们各自的优劣点。之后还提供了绘制对应图表的 Matplotlib 代码。
Matplotlib 是一个颇为流行的 Python 库,能够助力你迅速且便捷地构建数据可视化图表。不过,每当开启一个新的项目,都得重新对数据、参数、图形以及绘图方式进行设置,这是极为枯燥且无聊的。本文将会介绍 5 种数据可视化的方法,并且会用 Python 以及 Matplotlib 编写一些快速且易用的可视化函数。下图展示了选择正确可视化方法的导向图。
选择正确可视化方法的导向图。
散点图能直接看到原始数据的分布,所以对于展示两个变量之间的关系很有用。你可以用颜色把数据分组,以此来观察不同组数据之间的关系,就如下面的图所展示的那样。你也能够添加另一个参数,像数据点的半径,来编码第三个变量,进而可视化三个变量之间的关系,如同下方第二个图所示。
[id_1067557502]
用颜色分组的散点图,点半径作为第三个变量表示国家规模。
首先进行代码部分的操作。我们把 Matplotlib 的 pyplot 导入并记作 plt 。接着调用函数 plt.subplots() 去创建新的图。之后把 x 轴和 y 轴的数据传递给这个函数,再把得到的结果传递给 ax.scatter() ,以此来画出散点图。我们能够设置点的半径,能够设置点的颜色,还能够设置 alpha 透明度。我们甚至可以把 y 轴设置为对数尺寸。最后,我们可以为图指定标题,也可以为坐标轴指定标签。
import matplotlib.pyplot as plt
import numpy as np
def scatterplot(x_data, y_data, x_label="", y_label="", title="", color = "r", yscale_log=False):
# Create the plot object
_, ax = plt.subplots()
绘制数据,设定大小(s)、颜色以及透明度(alpha)。
# of the points
ax 进行散点图绘制,其横坐标为 x_data,纵坐标为 y_data,点的大小 s 为10, color = color, alpha = 0.75)
if yscale_log == True:
ax.set_yscale('log')
给坐标轴添加标注并提供一个标题。
ax.set_title(title)
ax.set_xlabel(x_label)
ax.set_ylabel(y_label)
当一个变量随另一个变量变化的幅度大时,也就是它们有高协方差时,线图很有用。从下图能看到,所有专业课程的相对百分数随年代变化幅度大。用散点图画这些数据会杂乱无章,难以看清本质。而线图适合这种情况,因为它能快速总结两个变量的协方差。在这里,我们也可以用颜色将数据分组。
线图示例。
以下是线图的实现代码,它与散点图的代码结构较为相似,只是在变量设置方面有一些细微的变化。
def lineplot(x_data, y_data, x_label="", y_label="", title=""):
# Create the plot object
_, ax = plt.subplots()
绘制最佳拟合线,设定线宽(lw)、颜色以及
这条线的透明度(α)
ax 绘制 x_data 和 y_data 的图形,线条宽度为2, color = '#539caf', alpha = 1)
# Label the axes and provide a title
ax.set_title(title)
ax.set_xlabel(x_label)
ax.set_ylabel(y_label)
直方图对于观察或深入了解数据点的分布很有帮助。我们绘制了频率与 IQ 的直方图,通过它我们能够直观地知晓分布的集中度(方差)以及中位数,还能了解到该分布的形状近似为高斯分布。使用这种柱形(而非散点图等)能够清晰地将每一个箱体(X 轴的一个等距区间)间频率的变化可视化。使用箱体(离散化)有助于我们观察到“更完整的图像”。因为若使用所有数据点而不进行离散化,就无法观察到近似的数据分布,在可视化过程中可能会存在很多噪声,这样就只能近似地描述,而不能准确地描述真正的数据分布。
直方图案例
下面展示了 Matplotlib 中绘制直方图的代码。这里有两个需注意的步骤:其一,n_bins 参数可控制直方图的箱体数量或离散化程度。较多的箱体或柱体能给我们提供更多信息,但也会引入噪声并使我们所观察到的全局分布图像变得不太规则。更少的箱体能给我们带来更多的全局信息,这样我们即便在缺少细节信息时,也能观察到整体分布的形状。其次,cumulative 参数属于布尔值类型,它具备这样的功能,即让我们能够选择直方图是否为累积的,也就是能够选择概率密度函数(PDF)或者累积密度函数(CDF)。
def histogram数据、分箱数量、是否累积(cumulative=False)、x 轴标签(x_label = )"", y_label = "", title = ""):
_, ax = plt.subplots()
ax.hist 这个函数用于绘制数据的直方图。它接受 data 作为要绘制的数据,n_bins 表示直方图的箱数,cumulative 表示是否是累积直方图,color 表示直方图的颜色。'#539caf')
ax.set_ylabel(y_label)
ax.set_xlabel(x_label)
ax.set_title(title)
如果我们期望比较数据里两个变量的分布,那么或许有人会觉得我们得制作两个单独的直方图,然后把它们拼接起来去进行比较。然而实际上,Matplotlib 有着更优的办法,我们能够用不同的透明度把多个直方图叠加起来。如下图所示,将透明度设置为 0.5 且均匀分布,这样我们就能够把它叠加在高斯分布上,从而允许用户在同一图表上把两个分布绘制出来并进行比较。
叠加直方图
在叠加直方图的代码里,我们得留意一些问题。其一,所设定的水平区间要能同时契合两个变量的分布。其二,依据水平区间的范围以及箱体数,能够算出每个箱体的宽度。另外,在一个图表上绘制两个直方图时,要确保其中一个直方图具有更大的透明度。
将两个直方图叠加起来以便对它们进行比较。
def overlaid_histogram(data1, data2, n_bins = 0, data1_name="", data1_color="#539caf", data2_name="", data2_color="#7663b0", x_label="", y_label="", title=""):
设置箱子的边界,以便能够对这两个分布进行公平的比较。
max_nbins = 10
data_range 等于由两个元素组成的列表,第一个元素是 data1 中的最小值与 data2 中的最小值中的较小值,第二个元素是 data1 中的最大值与 data2 中的最大值中的较大值。
binwidth = (data_range[1] - data_range[0]) / max_nbins
if n_bins == 0
bins 等于从 data_range 的起始值到结束值以一定步长生成的数组。0], data_range[1] + binwidth, binwidth)
else:
bins = n_bins
# Create the plot
_, ax = plt.subplots()
使用 ax 绘制数据 data1 的直方图,设置 bins 为指定的 bins,颜色为 data1_color,透明度为指定的透明度。1, label = data1_name)
ax.hist 对 data2 进行绘图操作,设置了 bins 为 bins,颜色为 data2_color,透明度为 alpha 。0.75, label = data2_name)
ax.set_ylabel(y_label)
ax.set_xlabel(x_label)
ax.set_title(title)
ax.legend(loc = 'best')
条形图
当对类别数很少(
常规条形图为图 1 。在 barplot() 函数里,x_data 代表 x 轴上的不同类别,y_data 代表 y 轴上的条形高度。误差条形是添加在每个条形中心的线,能够用来表示标准差。
常规条形图
分组条形图能够让我们对多个类别变量进行比较。从图中可以看出,我们的第一个变量会依据不同的分组(如 G1、G2 等)而发生变化,并且我们在每一组当中去比较不同的性别。就像代码所显示的那样,y_data_list 变量如今实际上是由一组列表构成的,其中每一个子列表都代表了一个不同的组。然后我们依次遍历每一个组,接着在 X 轴上绘制柱体以及与之对应的数值。每一个分组的不同类别会用不同的颜色来表示。
分组条形图
堆叠条形图很适合可视化不同变量的分类构成。在接下来的堆叠条形图里,我们对工作日的服务器负载进行了比较。利用不同颜色的方块堆叠在同一条形图上,我们能够轻松地查看并知晓哪台服务器每天的工作效率最高,以及同一服务器在不同天数的负载大小。绘制该图的代码风格与分组条形图相同。我们会循环遍历每一组。这次我们是在旧的柱体之上绘制新的柱体,而不是在旁边绘制。
堆叠条形图
def barplotx_data 以及 y_data 还有 error_data ,并且 x_label 为"", y_label="", title=""):
_, ax = plt.subplots()
绘制条形图,将它们放置在 x 轴刻度标记的中心位置。
ax 绘制了以 x_data 为 x 轴数据、y_data 为 y 轴数据且颜色为指定颜色的条形图。'#539caf', align = 'center')
绘制误差线以显示标准偏差,将线条样式设置为“无”
以下是改写后的句子:去除点与点之间的线条。
ax 绘制误差线,x 数据为 x_data,y 数据为 y_data,y 误差为 error_data,颜色为指定颜色。'#297083', ls = 'none', lw = 2, capthick = 2)
ax.set_ylabel(y_label)
ax.set_xlabel(x_label)
ax.set_title(title)
def stackedbarplotx_data 以及 y_data_list、colors,还有 y_data_names 。"", x_label="", y_label="", title=""):
_, ax = plt.subplots()
绘制条形图,每次绘制一个类别。
for i in range(0, len(y_data_list)):
if i == 0:
ax 绘制 x 数据与 y_data_list 中的第 i 个数据的条形图,颜色为 colors 中的第 i 个颜色,且对齐方式为……'center', label = y_data_names[i])
else:
对于第一个之后的每一个类别,其底部的情况是…… ;每个除第一个之外的类别,其底部…… ;在第一个类别之后的每一类,其底部……
酒吧将处于最后一个类别中的顶端位置。
ax.bar(x_data, y_data_list[i]),其颜色为 colors[i],底部为 y_data_list[i - 1]1], align = 'center', label = y_data_names[i])
ax.set_ylabel(y_label)
ax.set_xlabel(x_label)
ax.set_title(title)
ax.legend(loc = 'upper right')
def groupedbarplot(x_data, y_data_list, colors, y_data_names="", x_label="", y_label="", title=""):
_, ax = plt.subplots()
所有条形在一个 x 位置的总宽度
total_width = 0.8
每个单独条形的宽度
计算得出的 ind_width 等于 total_width 除以 y_data_list 的长度。
此操作会将每个条形簇围绕 x 刻度标记居中。
alteration 等于从负的(total_width 除以 2)到正的(total_width 除以 2),以步长为 1 进行取值所生成的数组。2), total_width/2, ind_width)
# Draw bars, one category at a time
for i in range(0, len(y_data_list)):
与之前所画的那些有重叠之处。
ax 对 x_data 加上 alteration[i] 进行 bar 操作,使用 y_data_list[i] 作为数据,颜色为 colors[i],标签为 y_data_names[i],宽度为 ind_width
ax.set_ylabel(y_label)
ax.set_xlabel(x_label)
ax.set_title(title)
ax.legend(loc = 'upper right')
箱线图
上述直方图对可视化变量分布很有用。然而,当我们需要更多信息时该怎么办呢?我们或许需要清晰地将标准差可视化,也可能会出现中位数和平均值差值很大(存在很多异常值)的情况,所以需要更细致的信息。还可能会出现数据分布很不均匀等情况。
箱线图能够给我们提供所需的全部信息。实线箱的底部代表第一个四分位数,其顶部则代表第三个四分位数,箱内的线代表第二个四分位数也就是中位数。虚线表示数据的分布范围。
箱线图是对单个变量的可视化,所以它的设置很简单。x_data 是变量的列表。Matplotlib 函数 boxplot() 会为 y_data 的每一列或 y_data 序列中的每个向量绘制一个箱线图,这样一来,x_data 中的每个值就对应着 y_data 中的一列或一个向量。
箱线图示例。
def boxplot(x_data, y_data, base_color="#539caf", median_color="#297083", x_label="", y_label="", title=""):
_, ax = plt.subplots()
绘制箱线图,明确所需的样式。可以分别绘制不同数据集或变量的箱线图,以展示数据的分布特征。通过设置箱线图的各种参数,如 whisker 的长度、中位数的标记等,来满足特定的可视化需求。还可以将箱线图与其他图表类型结合使用,以更全面地展示数据信息。
ax.boxplot(y_data
语言风格:保持原文风格,去掉最前面的序号,将长句拆分成多个小分句,分句越短越好。具体来说,就是把原来的长句拆分成几个较短的句子,每个句子表达一个相对独立的意思,同时保留原文的意思和语言风格,不穿插英文单词,也不修改专有名词。例如:“语言风格保持不变,去掉序号,拆分长句为短句,短句表达独立意思,保留原意,不穿插英文,不修改专有名词。”True
# Properties of median line
中位数属性为 { } ,'color': median_color}
# Properties of box
, boxprops = {'color': base_color, 'facecolor': base_color}
# Properties of whiskers
whiskerprops 为一个对象,其中包含了一些相关的属性或配置。 它可能用于与胡须相关的操作或呈现。 这些属性可能与胡须的形状、颜色、长度等方面有关。 具体的属性内容取决于使用 whiskerprops 的上下文和目的。'color': base_color}
# Properties of whisker caps
, capprops = {'color': base_color})
绘制每个框。这将标签设置为我们想要的那些。
ax.set_xticklabels(x_data)
ax.set_ylabel(y_label)
ax.set_xlabel(x_label)
ax.set_title(title)
箱线图代码
结论
本文介绍了 5 种方便且易用的 Matplotlib 数据可视化方法。把可视化过程进行抽象并转化为函数,能够使代码变得更易读且更易用。希望你喜欢!