文章目录
- 单变量图的类型
- 1.直方图(histogram plot)
- 2.密度图(density plot)
- 3.Q-Q 图(Quantile- Quantile plot,又称分位图)
- 4.P-P 图(Probability-Probability plot)
- 5.经验分布函数图(Empirical Distribution Function,EDF)
- 直方图
单变量图(chart for one variable)是指使用数据组的一个变量进行相应图的绘制。想要可视化这个变量,就需要根据不同的数据变量类型绘制图。数据变量分为连续变量(continuous variable)和离散型变量(discrete variable)。
单变量图的类型
1.直方图(histogram plot)
直方图是一种用于表示数据分布和离散情况的统计图形,它的外观和柱形图相近,但表达的含义和柱形图却相差较大。
首先需要对数据组进行分组,然后统计每个分组内数据元的个数,最后使用一系列宽度相等、高度不等的长方形来表示相应的每个分组内的数据元个数。基于“统计数据频数”的绘图思想在一些带颜色映射的图绘制中较为常用。
2.密度图(density plot)
密度图(又称为密度曲线图)作为直方图的一个变种类型,使用曲线(多数情况下为平滑样式,但也会因核函数的不同而出现直角样式)来体现数值水平,其主要功能是体现数据在连续时间段内的分布状况。
和直方图相比,密度图不会因分组个数而导致数据显示不全,从而能够帮助用户有效判断数据的整体趋势。当然,选择不同的核函数,绘制的核密度估计图不尽相同。在一些科研论文绘图过程中,密度图的纵轴可以是频数(count)或密度(density)。
3.Q-Q 图(Quantile- Quantile plot,又称分位图)
Q-Q 图的本质是概率图,其作用是检验数据分布是否服从某一个分布。Q-Q 图检验数据分布的关键是通过绘制分位数来进行概率分布比较。首先选好区间长度,Q-Q 图上的点 (x, y) 对应第一个分布(X 轴)的分位数和第二个分布(Y 轴)相同的分位数。因此可以绘制一条以区间个数为参数的曲线。如果两个分布相似,则该 Q-Q 图趋近于落在 y = x 线上。如果两个分布线性相关,则点在 Q-Q 图上趋近于落在一条直线上。
例如,对于正太分布的 Q-Q 图,就是以标准正太分布的分位数作为横坐标,样本数据值为纵坐标的散点图。而想要使用 Q-Q 图对某一样本数据进行正态分布的鉴别时,只需观察 Q-Q 图上的点是否近似在一条直线附近,且该条直线的斜率为标准差,截距为均值。
Q-Q 图不但可以检验样本数据是否符合某种数据分布,而且可以通过对数据分布形状的比较,来发现数据在位置、标度和偏度方面的属性。
在一般的学术研究中,使用直方图或密度图观察数据分布的频次要远高于 Q-Q 图。
4.P-P 图(Probability-Probability plot)
P-P 图是根据变量的累积概率与指定的理论分布累积概率的关系绘制的图形,用于直观地检验样本数据是否符合某一概率分布。当检验样本数据符合预期分布时,P-P 图中的各点将会呈现一条直线。P-P 图与 Q-Q 图都用来检验样本数据是否符合某种分布,只是检验方法不同而已。
5.经验分布函数图(Empirical Distribution Function,EDF)
在统计学中,经验分布函数也被称为经验累积分布函数。经验分布函数是一个与样本的检验测度相关的分布函数。对于被测变量的某个值,该值的分布函数值表示所有检验样本中小于或等于该值的样本的比例。经验分布函数图用来检验样本数据是否符合某种预期分布。
直方图
在 Matplotlib 中,我们可使用 axes.Axes.Hist ()
函数绘制直方图。
在 axes.Axes.Hist ()
函数中,参数 x 为要绘制的样本数据;参数 bins 用于定义分布区间,该参数的值可设置成整数、给定数值序列或字符串,默认为数值类型且值为 10。当参数 bins 的值为整数时,定义范围内等宽 bin 的数量。当参数 bins 的值为自定义数值序列时,定义 bin 边缘数值,包括第一个 bin 的左边缘和最后一个 bin 的右边缘。
注意,在上述这种情况下,bin 的间距可能不相等。
当参数 bins 的值为字符串类型时,可选“auto”“fd”“rice”和“sqrt”等值。axes.Axes.Hist ()
函数的参数 density 对应的值为布尔类型,该参数决定绘图结果是否为密度图,默认值为 False。
下面为分别使用 Matplotlib、ProPlot 和 SciencePlots 绘制的直方图示例:
(a)和(c)都是基于 Matplotlib 绘制的可视化结果,且(c)是使用 SciencePlots 包中的绘图主题进行绘制。下面给出(a)的核心绘制代码。
import numpy as np
import pandas as pd
hist_data = pd.read_excel(r"柱形图绘制数.xlsx")
#(a) Matplotlib绘制的直方图
import matplotlib.pyplot as plt
plt.rcParams["font.family"] = "Times New Roman"
plt.rcParams["axes.linewidth"] = 1
plt.rcParams["axes.labelsize"] = 15
plt.rcParams["xtick.minor.visible"] = True
plt.rcParams["ytick.minor.visible"] = True
plt.rcParams["xtick.direction"] = "in"
plt.rcParams["ytick.direction"] = "in"
plt.rcParams["xtick.labelsize"] = 12
plt.rcParams["ytick.labelsize"] = 12
plt.rcParams["xtick.top"] = False
plt.rcParams["ytick.right"] = False
hist_x_data = hist_data["hist_data"].values
bins = np.arange(0.0,1.5,0.1)
fig,ax = plt.subplots(figsize=(4,3.5),dpi=100,facecolor="w")
hist = ax.hist(x=hist_x_data, bins=bins,color="#3F3F3F",
edgecolor ='black',rwidth = 0.8)
ax.tick_params(axis="x",which="minor",top=False,bottom=False)
ax.set_xticks(np.arange(0,1.4,0.1))
ax.set_yticks(np.arange(0.,2500,400))
ax.set_xlim(-.05,1.3)
ax.set_ylim(0.0,2500)
ax.set_xlabel('Values', )
ax.set_ylabel('Frequency')
plt.show()
(b)的核心绘制代码如下:
#(b)ProPlot绘制的直方图
import proplot as pplt
from proplot import rc
rc["axes.labelsize"] = 15
rc['tick.labelsize'] = 12
rc["suptitle.size"] = 15
hist_x_data = hist_data["hist_data"].values
bins = np.arange(0.0,1.5,0.1)
fig = pplt.figure(figsize=(3.5,3))
ax = fig.subplot()
ax.format(abc='a.', abcloc='ur',abcsize=16,
xlabel='Values', ylabel='Frequency',
xlim = (-.05,1.3),ylim=(0,2500))
hist = ax.hist(x=hist_x_data, bins=bins,color="#3F3F3F",
edgecolor ='black',rwidth = 0.8)
plt.show()
(c)使用了 SciencePlots 中优秀的绘图主题,用户只需要在绘制脚本前添加如下代码。
with plt.style.context(['science']):
核心代码如下:
import pandas as pd
import numpy as np
import seaborn as sns
import matplotlib.pyplot as plt
hist_x_data = hist_data["hist_data"].values
bins = np.arange(0.0,1.5,0.1)
with plt.style.context(['science']):
fig,ax = plt.subplots(figsize=(4,3.5),dpi=100,facecolor="w")
hist = ax.hist(x=hist_x_data, bins=bins,color="#3F3F3F",
edgecolor ='black',rwidth = 0.8)
ax.set_xlim(-.05,1.4)
ax.set_ylim(0.0,2500)
ax.set_xlabel('Values', )
ax.set_ylabel('Frequency')
plt.show()
有时,为了显示一些必要的统计信息,我们需要在直方图中添加正态分布曲线(normal distribution curve)、均值线(mean line)和中位数线(median line)等,或者以短竖线样式在 X 轴位置处表示数据点。
Matplotlib 绘制的添加了正态分布曲线和中位数线的直方图示例如下:
带统计信息的直方图的绘制难点在于正态分布曲线的计算和绘制。我们可以使用 scipy.Stats.Norm ()
函数对绘制数据实现正态拟合,计算出概率密度函数(Probability Density Function,PDF)结果。
由于概率密度函数结果是归一化的,即曲线下方的面积为 1,而直方图的总面积是样本数和每个 bin 宽度的乘积,因此,对概率密度函数结果与样本个数、bin 宽度值相乘的结果进行绘制,即可将绘制的曲线缩放到直方图的高度。
上图绘制代码如下:
import numpy as np
import pandas as pd
hist_data = pd.read_csv(r"直方图绘制02.xlsx")
hist_x_data = hist_data02["hist_data"].values
X_mean = np.mean(hist_x_data)
# 图3-2-2 带统计信息的直方图绘制示例
from scipy.stats import norm
import matplotlib.pyplot as plt
bins=15
hist_x_data = hist_data02["hist_data"].values
Median = np.median(hist_x_data)
mu, std = norm.fit(hist_x_data)
fig,ax = plt.subplots(figsize=(5,3.5),dpi=100,facecolor="w")
hist = ax.hist(x=hist_x_data, bins=bins,color="gray",
edgecolor ='black',lw=.5)
# Plot the PDF.
xmin, xmax = min(hist_x_data),max(hist_x_data)
x = np.linspace(xmin, xmax, 100) # 100为随机选择,值越大,绘制曲线越密集
p = norm.pdf(x, mu, std)
N = len(hist_x_data)
bin_width = (x.max() - x.min()) / bins
ax.plot(x, p*N*bin_width,linewidth=1,color="r",label="Normal Distribution Curve")
# 添加平均值线
ax.axvline(x=Median,ls="--",lw=1.2,color="b",label="Median Line")
ax.set_xlabel('Values')
ax.set_ylabel('Count')
ax.legend(frameon=False)
plt.show()
下面是使用 ProPlot 和 SciencePlots 绘制的带统计信息的直方图示例。
(a)中的a. 为图形序号,可根据实际情况添加。除使用上述方式绘制直方图以外,我们还可以使用 Seaborn 中的 histplot () 函数绘制,该函数在使用上更加灵活。
# (a)使用ProPlot绘制的带统计信息的直方图示例
from scipy.stats import norm
from proplot import rc
rc["axes.labelsize"] = 15
rc['tick.labelsize'] = 12
rc["suptitle.size"] = 15
bins=15
hist_x_data = hist_data["hist_data"].values
Median = np.median(hist_x_data)
mu, std = norm.fit(hist_x_data)
fig = pplt.figure(figsize=(3.5,3))
ax = fig.subplot()
ax.format(abc='a.', abcloc='ur',abcsize=16,
xlabel='Values', ylabel='Count')
hist = ax.hist(x=hist_x_data, bins=bins,color="gray",
edgecolor ='black',lw=.5)
# Plot the PDF.
xmin, xmax = min(hist_x_data),max(hist_x_data)
x = np.linspace(xmin, xmax, 100)
p = norm.pdf(x, mu, std)
N = len(hist_x_data)
bin_width = (x.max() - x.min()) / bins
ax.plot(x, p*N*bin_width,linewidth=1,color="r",label="Normal Distribution Curve")
# 添加平均值线
ax.axvline(x=Median,ls="--",lw=1.2,color="b",label="Median Line")
ax.legend(ncols=1,frameon=False,loc="ur")
plt.show()
# (b)使用SciencePlots 绘制的带统计信息的直方图示例
from scipy.stats import norm
bins=15
hist_x_data = hist_data["hist_data"].values
Median = np.median(hist_x_data)
mu, std = norm.fit(hist_x_data)
xmin, xmax = min(hist_x_data),max(hist_x_data)
x = np.linspace(xmin, xmax, 100)
p = norm.pdf(x, mu, std)
N = len(hist_x_data)
bin_width = (x.max() - x.min()) / bins
with plt.style.context(['science']):
fig,ax = plt.subplots(figsize=(4,3.5),dpi=100,facecolor="w")
hist = ax.hist(x=hist_x_data, bins=bins,color="gray",
edgecolor ='black',lw=.5)
ax.plot(x, p*N*bin_width,linewidth=1,color="r",label="Normal Distribution Curve")
# 添加平均值线
ax.axvline(x=Median,ls="--",lw=1.2,color="b",label="Median Line")
ax.set_xlabel('Values')
ax.set_ylabel('Count')
ax.legend(frameon=False)
plt.show()
参考书籍:宁海涛.科研论文配图绘制指南——基于Python[M].北京:人民邮电出版社,2023:47-49.