掌握MATLAB直方图函数:数据分析与可视化
引言
在数据分析领域,理解数据的分布是至关重要的一步。直方图(Histogram)作为一种基础而强大的统计图形工具,能够直观地展示数值型数据的分布形态、集中趋势、离散程度以及是否存在异常值。它通过将数据范围划分为一系列连续的“区间”或“箱体”(bins),然后统计每个区间内数据点的数量或频率,并以条形图的形式展现出来。
MATLAB® 作为一款功能强大的数值计算和编程环境,提供了卓越的数据处理、分析和可视化能力。其直方图函数不仅易于使用,而且功能丰富,能够满足从基本的数据探索到复杂的统计建模的各种需求。本文将深入探讨MATLAB中的直方图函数,包括其核心用法、高级定制选项、不同函数的选择、以及在实际数据分析中的应用,旨在帮助读者全面掌握MATLAB直方图的精髓,从而提升数据分析与可视化的水平。
1. 直方图基础:理解其原理与价值
在深入MATLAB的具体函数之前,我们首先要理解直方图的核心概念及其在数据分析中的价值。
1.1 什么是直方图?
直方图是一种二维图形,它将数据值域分割成若干个不重叠的子区间(或称“箱子”,bins)。对于每个子区间,直方图统计落入该区间内的数据点的数量(频率)或所占的比例(相对频率),并用一个与该区间宽度相等、高度与频率成正比的矩形条来表示。这些矩形条彼此相邻,共同描绘出数据的整体分布轮廓。
1.2 直方图的构成要素
- 数据 (Data):需要分析的数值型数据集。
- 箱体 (Bins):数据范围被划分成的连续区间。箱体的数量和宽度是影响直方图外观和解释的关键参数。
- 箱体边缘 (Bin Edges):定义每个箱体起止点的数值。
- 频率/计数 (Frequency/Count):落入每个箱体中的数据点数量。
- 高度 (Height):表示每个箱体的频率或相对频率。
1.3 直方图在数据分析中的价值
- 揭示数据分布形态:是正态分布、偏态分布(左偏、右偏)、均匀分布、双峰分布还是其他复杂形态?这对于选择合适的统计模型至关重要。
- 识别集中趋势:数据的中心位置在哪里?众数(频率最高的箱体)能提供这方面的信息。
- 衡量离散程度:数据是紧密聚集还是广泛分散?直方图的宽度和峰值可以给出提示。
- 检测异常值 (Outliers):远离主体分布的孤立条形可能指示异常数据点。
- 比较不同数据集:通过在同一坐标系中绘制多个直方图,可以直观地比较不同数据集的分布差异。
- 评估模型拟合度:将数据的经验分布与理论分布(如正态分布)进行比较。
2. MATLAB 直方图核心函数:histogram 与 histcounts
MATLAB 提供了现代化的 histogram 函数以及与其紧密相关的 histcounts 函数来创建和操作直方图。了解这两个函数的用法是掌握MATLAB直方图的关键。
2.1 histogram() 函数:绘制直观的直方图
histogram() 是MATLAB中推荐用于创建直方图的函数,它提供高度的灵活性和丰富的定制选项。
2.1.1 基本用法
最简单的用法是直接传入一个数值向量:
“`matlab
% 生成一组随机数据(标准正态分布)
data = randn(1000, 1);
% 绘制基本直方图
figure;
h = histogram(data); % ‘h’ 是一个 Histogram 对象
title(‘基本直方图’);
xlabel(‘数据值’);
ylabel(‘频数’);
“`
执行上述代码,MATLAB会自动选择合适的箱体数量和宽度,并绘制出数据的频数直方图。
2.1.2 控制箱体 (Bins)
箱体的选择对直方图的外观和解释有显著影响。MATLAB提供了多种方式来精确控制箱体。
-
指定箱体数量 (
NumBins):
通常,箱体数量越多,直方图细节越丰富,但也可能引入更多噪声;箱体数量越少,直方图越平滑,但也可能掩盖重要细节。“`matlab
figure;
subplot(1, 2, 1);
histogram(data, ‘NumBins’, 10); % 10个箱体
title(‘NumBins = 10’);
xlabel(‘数据值’);
ylabel(‘频数’);subplot(1, 2, 2);
histogram(data, ‘NumBins’, 50); % 50个箱体
title(‘NumBins = 50’);
xlabel(‘数据值’);
ylabel(‘频数’);
“` -
指定箱体宽度 (
BinWidth):
直接设置每个箱体的宽度。matlab
figure;
histogram(data, 'BinWidth', 0.2); % 每个箱体宽度为0.2
title('BinWidth = 0.2');
xlabel('数据值');
ylabel('频数'); -
指定箱体边缘 (
BinEdges):
这是最精确的控制方式,你可以完全自定义每个箱体的起始和结束点。BinEdges是一个递增的向量,它的长度是箱体数量加一。matlab
% 定义自定义箱体边缘
custom_edges = -3:0.5:3; % 从-3到3,步长0.5
figure;
histogram(data, 'BinEdges', custom_edges);
title('自定义BinEdges');
xlabel('数据值');
ylabel('频数'); -
自动箱体选择方法 (
BinMethod):
MATLABhistogram函数默认使用一种优化的自动箱体选择算法。但你也可以指定其他算法,如'auto'(默认),'scott','freedman-diaconis','rice','sqrt'。这些算法根据不同的统计准则来确定箱体数量和宽度,适用于不同的数据特性。matlab
figure;
subplot(2, 2, 1); histogram(data, 'BinMethod', 'auto'); title('Auto (Default)');
subplot(2, 2, 2); histogram(data, 'BinMethod', 'scott'); title('Scott');
subplot(2, 2, 3); histogram(data, 'BinMethod', 'freedman-diaconis'); title('Freedman-Diaconis');
subplot(2, 2, 4); histogram(data, 'BinMethod', 'rice'); title('Rice');
sgtitle('不同BinMethod的直方图');
选择哪种方法取决于数据的特性和分析目标。例如,'freedman-diaconis'和'scott'方法在处理具有较厚尾部的数据时可能表现更好,而'rice'方法倾向于产生更多的箱体。
2.1.3 数据归一化 (Normalization)
直方图不仅仅用于展示频数,还可以用于展示数据的概率分布。Normalization 参数允许你将直方图的高度归一化为不同的统计量。
'count'(默认):每个条形的高度代表落入该箱体的数据点数量(频数)。-
'probability'(概率):每个条形的高度代表落入该箱体的数据点数量除以总数据点数量(相对频数)。所有条形高度之和为1。matlab
figure;
histogram(data, 'Normalization', 'probability');
title('概率直方图');
xlabel('数据值');
ylabel('概率'); -
'pdf'(概率密度函数):每个条形的高度被归一化,使得直方图的总面积(所有条形宽度乘以高度之和)为1。这使得直方图可以近似连续型随机变量的概率密度函数 (PDF)。对于等宽箱体,条形高度表示概率密度。matlab
figure;
histogram(data, 'Normalization', 'pdf');
title('概率密度直方图');
xlabel('数据值');
ylabel('概率密度');
重要提示:在'pdf'模式下,条形的高度 不直接 表示概率,而是概率密度。一个区间内的概率是该区间的条形面积。 -
'cdf'(累积分布函数):每个条形的高度代表小于或等于该箱体上边缘的数据点的累积概率。matlab
figure;
histogram(data, 'Normalization', 'cdf');
title('累积分布直方图');
xlabel('数据值');
ylabel('累积概率'); -
'cumcount'(累积频数):每个条形的高度代表小于或等于该箱体上边缘的数据点的累积频数。matlab
figure;
histogram(data, 'Normalization', 'cumcount');
title('累积频数直方图');
xlabel('数据值');
ylabel('累积频数');
归一化选项的选择取决于你的分析目的。如果你想比较不同样本大小的数据集,'probability' 或 'pdf' 会更有用。如果你想了解数据落在某个值以下的百分比,'cdf' 是理想选择。
2.1.4 直方图的美化与定制
histogram 函数返回一个 Histogram 对象,你可以像操作其他图形对象一样来定制其外观。
-
颜色 (
FaceColor,EdgeColor):matlab
figure;
histogram(data, 'FaceColor', 'b', 'EdgeColor', 'k'); % 蓝色填充,黑色边框
title('自定义颜色的直方图'); -
透明度 (
FaceAlpha):当绘制多个直方图叠加时,透明度非常有用。matlab
data1 = randn(500, 1);
data2 = randn(500, 1) + 1; % 第二组数据均值偏移
figure;
hold on; % 允许在同一坐标轴上绘制多个图形
histogram(data1, 'Normalization', 'pdf', 'FaceColor', 'r', 'FaceAlpha', 0.5, 'BinWidth', 0.2);
histogram(data2, 'Normalization', 'pdf', 'FaceColor', 'b', 'FaceAlpha', 0.5, 'BinWidth', 0.2);
hold off;
title('叠加直方图');
xlabel('数据值');
ylabel('概率密度');
legend('数据1', '数据2'); -
线型 (
LineStyle), 线宽 (LineWidth):针对边框线。 -
其他通用图形属性:如
XLim,YLim,XLabel,YLabel,Title,Grid等都可以通过gca(Get Current Axes) 或直接在histogram之后设置。matlab
figure;
h = histogram(data, 'NumBins', 30, 'FaceColor', [0.7 0.9 0.7], 'EdgeColor', [0.3 0.3 0.3], 'LineWidth', 0.8);
title('详细定制的直方图', 'FontSize', 14);
xlabel('数据数值范围', 'FontSize', 12);
ylabel('频数', 'FontSize', 12);
grid on;
xlim([-4 4]); % 设置X轴范围
ylim([0 max(h.Values)*1.1]); % 设置Y轴范围
2.1.5 处理分类数据
MATLAB histogram 函数也可以直接处理分类数据 (Categorical Data)。
“`matlab
% 创建分类数据
categories = {‘A’, ‘B’, ‘C’, ‘A’, ‘B’, ‘A’, ‘C’, ‘D’, ‘A’, ‘B’};
categorical_data = categorical(categories);
figure;
histogram(categorical_data);
title(‘分类数据的直方图’);
xlabel(‘类别’);
ylabel(‘频数’);
“`
这实际上会生成一个条形图,显示每个类别的计数。
2.1.6 叠加理论分布
一个常见的应用是将数据的经验直方图与某个理论概率分布(如正态分布)进行比较,以评估数据是否符合该理论分布。
“`matlab
data_normal = randn(1000, 1) * 2 + 5; % 均值为5,标准差为2的正态分布数据
% 拟合数据到正态分布
pd = fitdist(data_normal, ‘Normal’);
figure;
hold on;
h_hist = histogram(data_normal, ‘Normalization’, ‘pdf’, ‘FaceColor’, ‘c’, ‘FaceAlpha’, 0.6);
% 获取直方图的箱体中心点,用于绘制理论PDF曲线
x_values = h_hist.BinEdges(1:end-1) + h_hist.BinWidth/2; % 使用箱体中心点
% 或者更平滑的曲线,在数据范围内生成更多点
x_curve = linspace(min(data_normal), max(data_normal), 200);
y_curve = pdf(pd, x_curve);
plot(x_curve, y_curve, ‘r-‘, ‘LineWidth’, 2);
hold off;
title(‘数据与正态分布PDF比较’);
xlabel(‘数据值’);
ylabel(‘概率密度’);
legend(‘数据直方图’, ‘拟合正态分布PDF’);
“`
2.2 histcounts() 函数:获取直方图数据而不绘图
有时我们需要的不是直观的图形,而是直方图的底层数据:每个箱体的计数和箱体边缘。histcounts() 函数正是为此而设计,它执行与 histogram 函数相同的计算,但不会生成图表。这在需要编程控制绘图或进行进一步的数值分析时非常有用。
2.2.1 基本用法
“`matlab
data = randn(1000, 1);
% 获取箱体计数和边缘
[counts, edges] = histcounts(data);
% counts: 一个向量,表示每个箱体中的数据点数量
% edges: 一个向量,表示箱体的边缘。长度比 counts 多1。
disp(‘箱体计数 (counts):’);
disp(counts);
disp(‘箱体边缘 (edges):’);
disp(edges);
% 你可以使用这些数据手动绘制一个条形图
figure;
bar(edges(1:end-1), counts, ‘histc’); % ‘histc’ 使得条形紧密相连
title(‘使用histcounts数据手动绘制直方图’);
xlabel(‘数据值’);
ylabel(‘频数’);
``bar(x, y, ‘histc’)
注意中的x通常是箱体的左边缘或中心点。这里我们使用edges(1:end-1)作为箱体的左边缘,‘histc’` 样式会使条形从这些点开始绘制,并且宽度延伸到下一个边缘。
2.2.2 控制箱体与归一化
histcounts 函数支持与 histogram 类似的箱体控制和归一化选项:NumBins, BinWidth, BinEdges, BinMethod, 以及 Normalization。
“`matlab
[counts_prob, edges_prob] = histcounts(data, ‘Normalization’, ‘probability’, ‘NumBins’, 20);
figure;
bar(edges_prob(1:end-1), counts_prob, ‘histc’);
title(‘使用histcounts和Normalization=\’probability\”);
xlabel(‘数据值’);
ylabel(‘概率’);
“`
2.2.3 多维直方图的准备 (简要提及)
虽然 histogram 主要用于一维数据,但 histcounts 有一个对应的 histcounts2 函数,用于二维数据的箱体计数,这是创建二维直方图或热力图的基础。
“`matlab
% 生成二维数据
x = randn(1000, 1);
y = randn(1000, 1) + x/2; % x和y有一定相关性
% 获取二维箱体计数和边缘
[N, Cedges, Redges] = histcounts2(x, y, ‘NumBins’, [20 20]); % 20×20个箱体
figure;
imagesc(Cedges(1:end-1), Redges(1:end-1), N’); % 使用imagesc可视化,N’进行转置以匹配坐标轴
set(gca, ‘YDir’, ‘normal’); % 修正y轴方向
colorbar;
title(‘二维数据的箱体计数 (histcounts2)’);
xlabel(‘X值’);
ylabel(‘Y值’);
``heatmap`)奠定了基础。
这为探索MATLAB的更高级可视化功能(如
3. hist 函数:旧版直方图函数 (了解即可)
在MATLAB R2014b及更早版本中,主要使用 hist 函数来创建直方图。虽然它在现代版本中仍然可用,但 histogram 函数提供了更多的灵活性、更好的性能和更直观的接口,因此强烈推荐使用 histogram。
hist 的基本用法:
“`matlab
data = randn(1000, 1);
figure;
hist(data); % 默认10个箱体
title(‘使用hist函数’);
xlabel(‘数据值’);
ylabel(‘频数’);
hist(data, 20); % 指定20个箱体
hist(data, -3:0.5:3); % 指定箱体中心点
“`
hist 函数的主要缺点是它通常需要用户指定箱体中心点或箱体数量,而不像 histogram 那样直接支持箱体边缘或多种归一化方式。在R2014b及以后版本中,当调用 hist 时,MATLAB会发出警告并建议使用 histogram。
4. 数据分析与可视化中的直方图应用案例
直方图在众多领域都有广泛应用。下面我们通过几个案例来展示其在数据分析和可视化中的强大作用。
4.1 质量控制与异常值检测
在工业生产中,产品尺寸或重量的分布通常应符合特定的规格。直方图可以帮助监控生产过程的稳定性,并检测异常批次或缺陷产品。
“`matlab
% 假设一批产品的重量数据,其中包含一些异常值
product_weights = [normrnd(100, 5, 900, 1); 80; 125; normrnd(100, 5, 90, 1); 150];
figure;
h = histogram(product_weights, ‘NumBins’, 50, ‘FaceColor’, ‘g’, ‘EdgeColor’, ‘k’);
title(‘产品重量分布与异常值检测’);
xlabel(‘重量 (g)’);
ylabel(‘频数’);
grid on;
% 可以在图上标注异常值范围或规格限
xline(85, ‘r–‘, ‘下限’); % 假设下限是85g
xline(115, ‘r–‘, ‘上限’); % 假设上限是115g
% 观察直方图,可以看到在80g和125g、150g附近有离群的条形,提示存在异常值。
“`
4.2 图像处理:像素强度分布
直方图在图像处理中非常有用,用于分析图像的像素强度分布,例如灰度图像的灰度直方图。
“`matlab
% 加载一个示例图像
img = imread(‘cameraman.tif’); % MATLAB自带的灰度图像
% 将图像数据转换为双精度浮点数,并展平为向量
img_data = double(img(:));
figure;
histogram(img_data, ‘NumBins’, 256, ‘FaceColor’, ‘gray’, ‘EdgeColor’, ‘none’);
title(‘灰度图像像素强度直方图’);
xlabel(‘像素强度 (0-255)’);
ylabel(‘频数’);
xlim([0 255]); % 灰度值范围
“`
通过观察图像直方图,可以判断图像的对比度、亮度。例如,如果直方图集中在左侧(低强度),图像可能偏暗;如果集中在右侧(高强度),图像可能偏亮;如果分布很窄,图像对比度可能很低。
4.3 金融数据分析:股票收益率分布
分析股票或其他资产的日收益率分布,有助于评估风险和波动性。金融数据通常表现出“厚尾”特性,即极端事件发生的概率比正态分布预测的要高。
“`matlab
% 模拟股票日收益率数据(假设有厚尾特性)
num_days = 2500;
returns = randn(num_days, 1) * 0.01; % 模拟正态部分
% 引入一些极端值,模拟厚尾
extreme_events_idx = randi(num_days, 50, 1);
returns(extreme_events_idx) = returns(extreme_events_idx) + sign(randn(50,1)) . (0.05 + rand(50,1)0.1);
figure;
hold on;
h_hist = histogram(returns, ‘Normalization’, ‘pdf’, ‘NumBins’, 50, ‘FaceColor’, [0.8 0.9 1], ‘EdgeColor’, ‘b’, ‘FaceAlpha’, 0.7);
% 拟合一个正态分布进行比较
pd_normal = fitdist(returns, ‘Normal’);
x_vals = linspace(min(returns)1.2, max(returns)1.2, 200);
plot(x_vals, pdf(pd_normal, x_vals), ‘r–‘, ‘LineWidth’, 1.5);
hold off;
title(‘股票日收益率分布’);
xlabel(‘日收益率’);
ylabel(‘概率密度’);
legend(‘实际收益率直方图’, ‘正态分布拟合’);
grid on;
“`
通过观察,我们可以看到实际收益率直方图的尾部比正态分布拟合曲线更“厚”,这验证了金融数据的厚尾特性。
4.4 比较不同组别的分布
在实验设计或A/B测试中,我们经常需要比较两组或多组数据的分布是否存在显著差异。
“`matlab
% 实验组和对照组数据
control_group = randn(500, 1) * 1.5 + 10; % 均值10
experiment_group = randn(500, 1) * 1.5 + 10.8; % 均值10.8
figure;
hold on;
histogram(control_group, ‘Normalization’, ‘pdf’, ‘BinWidth’, 0.5, ‘FaceColor’, [0.7 0.7 0.7], ‘EdgeColor’, ‘k’, ‘FaceAlpha’, 0.7);
histogram(experiment_group, ‘Normalization’, ‘pdf’, ‘BinWidth’, 0.5, ‘FaceColor’, [0.9 0.5 0.5], ‘EdgeColor’, ‘k’, ‘FaceAlpha’, 0.7);
hold off;
title(‘实验组与对照组数据分布比较’);
xlabel(‘测量值’);
ylabel(‘概率密度’);
legend(‘对照组’, ‘实验组’);
grid on;
“`
直观地,我们可以看到实验组的分布略微向右偏移,表明其测量值可能更高。这为进一步的统计检验(如t检验)提供了初步的视觉证据。
5. 直方图可视化最佳实践与常见陷阱
5.1 最佳实践
- 选择合适的箱体数量/宽度:没有一刀切的规则,但目标是平衡细节和平滑度。尝试不同的设置,找到最能揭示数据潜在结构的组合。过于少的箱体会隐藏细节,过于多的箱体会使图表过于嘈杂。
- 明确的标签和标题:
xlabel,ylabel,title是必不可少的,它们让读者能够快速理解图表内容。 - 使用颜色和透明度:当叠加多个直方图时,使用不同的颜色和透明度(
FaceAlpha)可以清晰地区分它们。 - 考虑归一化:根据分析目的选择正确的
Normalization方式。比较不同大小数据集时,'probability'或'pdf'是更好的选择。 - 添加参考线:如果数据有重要的阈值、平均值或规格限制,使用
xline或yline函数添加参考线可以增强图表的解释性。 - 网格线:适当的网格线可以帮助读者更好地阅读数值。
- 交互性:利用MATLAB的图形交互功能,如数据提示(
datacursormode),可以在直方图上悬停以查看特定条形的计数和箱体范围。
5.2 常见陷阱与注意事项
- 箱体选择不当:这是最常见的错误。
- 箱体太少:可能掩盖数据中的多峰性或其他重要结构。
- 箱体太多:可能使直方图过于稀疏,强调随机噪声而不是真实模式。
- 误解归一化:尤其是在使用
'pdf'归一化时,要记住条形的高度代表 概率密度,而不是概率。特定区间内的概率是该区间的条形 面积。 - 数据类型:直方图主要用于连续或离散的数值型数据。对于真正的分类数据,条形图 (
bar函数或histogram处理categorical类型) 更合适。 - 直方图不是条形图:虽然它们看起来相似,但直方图的箱体是连续的,表示数值范围;条形图的条形是离散的,表示独立的类别。
- 数据范围:确保直方图覆盖了数据的完整有效范围。如果箱体边缘设置不当,可能会遗漏极端值。
- 小样本量:当数据样本量很小时,直方图的形状可能会非常不规则且不稳定,难以从中得出可靠的结论。在这种情况下,其他探索性数据分析工具可能更合适。
6. 总结与展望
MATLAB的 histogram 函数及其辅助工具(如 histcounts)为数据分析师和科学家提供了一个强大、灵活且易于使用的直方图创建和定制平台。通过深入理解其各种参数(尤其是箱体控制和归一化选项),我们可以从数据中提取出更深层次的洞察,有效地可视化数据分布,并支持后续的统计建模和决策制定。
从基本的数据探索到复杂的统计推断,直方图始终扮演着不可或缺的角色。掌握MATLAB的直方图函数,意味着你获得了数据分析领域的一项核心技能,能够更自信、更有效地与数据进行对话,让数据的故事以最直观、最准确的方式呈现。
随着MATLAB功能的不断演进,我们可以期待未来会有更多高级的交互式直方图工具和更智能的自动分析功能。持续学习和实践,将使你在利用MATLAB进行数据分析和可视化方面走得更远。