直方图(Histogram)是一种统计图表,用于显示数据分布的形态。它通过一系列紧密排列的矩形条形图展示数据在各个区间的频率。每个条形的高度表示该区间的数据点数或频率。
直方图的构成
横轴(X轴):
表示数据的范围,被划分为若干个区间(bins)。每个区间的宽度相等。
区间的个数和宽度可以根据数据特点和分析目的调整。
纵轴(Y轴):
表示数据在各个区间中的频数或频率。
条形图的高度代表该区间包含的数据点数量。
直方图的绘制
直方图基本绘制
在本案例中,我们将使用Python和常用的可视化库来分析和可视化基因表达数据。首先,我们需要安装并导入必要的Python库。确保你已经安装了以下库:Pandas, Matplotlib, 和 Seaborn。
# 安装必要的库
pip install pandas matplotlib seaborn
我们使用一个示例基因表达数据集。假设这个数据集名为 gene_expression.xlsx
,包含三种不同组织(肝脏、肾脏、心脏)的某个基因的表达水平,每个组织包含150个样本数据。我们以肝脏的基因表达水平为例绘制直方图。
在绘制直方图时,matplotlib
库的 plt.hist
函数非常强大,提供了许多参数来定制图表的外观和行为。这里我们只介绍常用的参数,其中参数 x
指定要绘制直方图的数据。参数 bins
用于定义分箱的数量或边界,类型可以是整数、序列或字符串(如'auto'),默认为整数10。参数 density
类型为布尔值,如果为 True
,则绘制概率密度直方图(总面积为1),默认为 False
。参数 cumulative
类型为布尔值,如果为 True
,则绘制累积直方图,默认为False
。参数 histtype
用于指定直方图类型,可以是 'bar'
、'barstacked'
、'step'
或 'stepfilled'
,默认为 'bar'
。参数 orientation
用于指定直方图的方向,可以是 'horizontal'
或 'vertical'
,默认为 'vertical'
。参数 log
类型为布尔值,如果为 True
,则使用对数刻度,默认为 False
。参数color
可指定条形的颜色。参数 label
可指定图例标签。参数 data
可以用于传递数据对象(例如字典或pandas DataFrame),便于使用列名。下图为使用不同参数绘制的直方图实例。
不同参数绘制的直方图实例
可见使用不同的参数可绘制样式不同的直方图,图 a 的绘图代码如下所示:
import os
import pandas as pd
import matplotlib.pyplot as plt
# 从 Excel 文件中读取数据,确保路径和文件名正确
df = pd.read_excel('gene_expression.xlsx', sheet_name='GeneExpression')
# 设置字体和图形参数
plt.rcParams["font.family"] = "Arial"
plt.rcParams["axes.linewidth"] = 1
plt.rcParams["axes.labelsize"] = 14
plt.rcParams["xtick.labelsize"] = 12
plt.rcParams["ytick.labelsize"] = 12
# 绘制直方图
plt.figure(figsize=(6, 4))
plt.hist(df['Liver'], bins=10, color='blue', alpha=0.3)
# 设置坐标轴标签
plt.xlabel('Expression Level (RNA copies)')
plt.ylabel('Frequency')
# 调整图像布局,确保所有元素居中
plt.tight_layout()
# 确保保存路径存在
output_dir = '图像实例/第四章 生物医药领域的专业绘图'
if not os.path.exists(output_dir):
os.makedirs(output_dir)
# 保存图像
plt.savefig(os.path.join(output_dir, '图4-1-1 直方图绘制实例_a.png'), dpi=600)
# 显示图像
plt.show()
图 b 的绘图核心代码如下所示:
# 绘制直方图,直方图类型为步骤图(‘step’),绘制累计直方图(cumulative=True)
plt.figure(figsize=(6, 4))
plt.hist(df['Liver'], bins=10, color='blue', alpha=0.3, histtype='step', cumulative=True)
图 c 的绘图代码如下所示:
# 绘制直方图,直方图类型为步骤图(‘step’),绘制概率密度直方图(density=True)
plt.figure(figsize=(6, 4))
plt.hist(df['Liver'], bins=30, color='blue', alpha=0.3, density=True)
带有统计信息的直方图
在直方图中增加统计信息可以帮助更好地理解数据的分布和特征。常见的统计信息包括:
平均值 (Mean):数据的算术平均值。
中位数 (Median):数据的中位数,表示数据的中心位置。
标准差 (Standard Deviation):衡量数据分布的离散程度。
最小值和最大值 (Min and Max Values):数据的范围。
四分位数范围 (Interquartile Range, IQR):衡量数据集中趋势的范围,通常包括25%分位数和75%分位数。
样本数量(Number, N): 表示数据集中包含的样本个数。
下图除了绘制直方图外,还添加了相关的统计信息,平均值以红色虚线表示,并标注在图中国;中位数以绿色虚线表示,并标注在图中;标准差、最小值、最大值、四分位数范围 (IQR)信息和样本数量显示在图的左侧。此外,还在直方图上绘制了正态分布曲线。
带统计信息直方图绘制实例
在python中可以很容易的实现统计信息的计算,在本例中,我们使用 numpy
库的 mean()
和 median()
函数计算数据的均值和中位数;使用 numpy
库的 std()
函数计算数据的标准差;使用 numpy
库的 min()
和 max()
函数计算数据的最小值和最大值;使用 numpy
库的 percentile()
函数计算数据的第 25 和第 75 百分位数,并计算它们的差值;使用 len()
函数计算数据集中的样本数量。关于正态分布曲线,我们使用 scipy.stats
模块的 norm.pdf()
函数计算给定均值和标准差的正态分布曲线上各点的概率密度值,为了使正态分布曲线与直方图匹配,我们需要将其高度按比例缩放。通过将正态分布曲线的最大高度缩放到直方图的最大柱高,使它们更好地对齐。绘图核心代码如下所示:
from scipy.stats import norm
# 计算统计信息
mean = np.mean(liver_data) # 计算均值
median = np.median(liver_data) # 计算中位数
std_dev = np.std(liver_data) # 计算标准差
min_val = np.min(liver_data) # 计算最小值
max_val = np.max(liver_data) # 计算最大值
iqr = np.percentile(liver_data, 75) - np.percentile(liver_data, 25)
n = len(liver_data) # 计算数据个数
# 添加统计信息
plt.axvline(mean, color='r', linestyle='dashed', linewidth=1, label='Mean line') # 添加均值虚线
plt.axvline(median, color='g', linestyle='dashed', linewidth=1, label='Median line') # 添加中位数虚线
# 添加标签,向右移动一定的距离(例如,1 个单位)
plt.text(mean + 1, plt.ylim()[1]*0.9, f'Mean: {mean:.2f}', color='r')
# 在均值线旁边添加文本标签
plt.text(median + 1, plt.ylim()[1]*0.8, f'Median: {median:.2f}', color='g') # 在中位数线旁边添加文本标签
# 绘制正态分布曲线
xmin, xmax = plt.xlim() # 获取 x 轴范围
x = np.linspace(xmin, xmax, 100) # 生成 x 轴上的点
p = norm.pdf(x, mean, std_dev) # 计算正态分布的 y 值
# 调整正态分布曲线的比例,使其与直方图匹配
scale_factor = max(counts) / max(p)
plt.plot(x, p * scale_factor, 'k', linewidth=1, label='Normal distribution') # 绘制正态分布曲线
# 显示额外的统计信息
plt.legend()
plt.figtext(0.15, 0.85, f'SD: {std_dev:.2f}', ha='left', fontsize=10, color='blue')
plt.figtext(0.15, 0.80, f'Min: {min_val:.2f}', ha='left', fontsize=10, color='blue')
plt.figtext(0.15, 0.75, f'Max: {max_val:.2f}', ha='left', fontsize=10, color='blue')
plt.figtext(0.15, 0.70, f'IQR: {iqr:.2f}', ha='left', fontsize=10, color='blue')
plt.figtext(0.15, 0.65, f'N: {n}', ha='left', fontsize=10, color='blue')
# 调整图像布局,确保所有元素居中
plt.tight_layout()