十年匠心定制 · 商业建站与技术教学双线并行 咨询热线:400-886-1026 service@lmnt.cn
ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

Matlab相关性分析实战:Pearson、Spearman、Kendall系数原理与应用

Matlab相关性分析实战:Pearson、Spearman、Kendall系数原理与应用 1. 项目概述相关性分析在数据科学中的基石作用在数据分析和建模的日常工作中我们常常需要回答一个核心问题两个或多个变量之间是否存在关联这种关联的强度和方向又如何无论是评估广告投入与销售额的关系还是研究气温与用电量的联动亦或是分析基因表达谱之间的共现模式相关性分析都是我们打开数据关系大门的第一把钥匙。它不关心因果只专注描述为我们后续的回归、分类、降维等复杂模型提供了至关重要的先验洞察。Matlab作为工程与科学计算领域的标杆工具其强大的矩阵运算能力和丰富的统计工具箱使得实现各类相关性分析变得异常高效和直观。今天我们就来深入聊聊Matlab中三种最经典的相关性系数皮尔逊Pearson、斯皮尔曼Spearman和肯德尔Kendall。很多朋友可能只用过corrcoef算个皮尔逊相关系数但面对非正态分布、存在异常值或者数据是等级秩次时该选哪个方法计算结果怎么解读假设检验的p值又代表了什么这些细节里的魔鬼恰恰是决定分析结论是否可靠的关键。我将结合自己多年处理实际数据集从金融时间序列到生物信号的经验带你不仅会用函数更懂其背后的原理、适用场景和那些容易踩坑的细节。2. 核心原理与算法选型三种系数的本质区别选择哪种相关性系数绝不是拍脑袋的决定而是由你的数据特性和分析目标所驱动的。理解它们的数学本质和适用前提是正确解读结果的第一步。2.1 皮尔逊积矩相关系数线性关系的度量尺皮尔逊相关系数通常记为r是我们最熟悉的老朋友。它衡量的是两个连续变量之间线性关系的强度和方向。其计算公式基于变量的协方差与各自标准差的乘积之比r Σ[(xi - x̄)(yi - ȳ)] / √[Σ(xi - x̄)² Σ(yi - ȳ)²]它的值域在[-1, 1]之间。r1表示完全正线性相关r-1表示完全负线性相关r0则表示没有线性相关关系。核心假设与注意事项 皮尔逊相关系数的有效性建立在几个关键假设之上1变量均为连续数据2变量之间呈双变量正态分布或至少近似正态3关系是线性的4数据对之间相互独立5没有显著的异常值。在实际操作中第2、3、5点最容易出问题。我见过太多案例因为一个强离群点的存在导致本应微弱的相关性被扭曲成强相关或强负相关。因此计算皮尔逊相关系数前务必通过散点图进行可视化检查这是不可或缺的一步。2.2 斯皮尔曼等级相关系数单调关系的侦察兵当数据不满足正态分布或者你怀疑变量间的关系是单调的即一个变量增加另一个变量也总是增加或总是减少但不一定是直线而非严格线性时斯皮尔曼相关系数记为ρ或rs就派上用场了。它的核心思想非常巧妙不直接使用原始数据而是将每个变量的观测值转换为等级rank然后对这两个等级序列计算皮尔逊相关系数。也就是说斯皮尔曼相关系数衡量的是两个变量的单调关系强度。实操心得 斯皮尔曼相关对异常值的鲁棒性远强于皮尔逊相关。因为异常值在转换为等级后其极端数值的影响被大大削弱例如最大值和次大值的等级差仅为1。在处理金融收益率、用户行为时长等经常出现尖峰或厚尾分布的数据时我通常会优先考虑斯皮尔曼相关。它回答的问题是“当X变大时Y是否也倾向于变大或变小”2.3 肯德尔等级相关系数一致性的评判官肯德尔相关系数通常记为τ同样基于数据的等级秩序但它从另一个角度——一致对与不一致对的比例——来衡量关联性。对于数据对 (xi, yi) 和 (xj, yj)如果 (xi xj) 且 (yi yj)或者 (xi xj) 且 (yi yj)我们称其为一致对。反之则为不一致对。肯德尔τ就是一致对数目与不一致对数目的差除以总的可能对数。τ (一致对数 - 不一致对数) / (总对数)肯德尔τ对样本量相对不敏感且更适用于等级数据或当数据中存在大量相同值结ties的情况。在心理学问卷评分、评委打分一致性分析等场景中应用广泛。2.4 选型决策流程图与对比总结为了更直观地做出选择我们可以遵循以下决策路径绘制散点图这是第一步也是最重要的一步。直观查看是否有明显非线性模式或异常点。检验正态性可以使用Q-Q图、Kolmogorov-Smirnov检验或Shapiro-Wilk检验对于小样本来判断。明确分析目标你到底关心的是精确的线性关系还是更一般的协同变化趋势单调关系为了便于快速查阅我将三者的核心区别总结如下表特性皮尔逊 (Pearson)斯皮尔曼 (Spearman)肯德尔 (Kendall)度量关系线性关系单调关系单调关系侧重秩序一致性数据要求连续双变量正态无异常值连续或等级无分布要求等级数据或可转换为等级的数据异常值敏感度非常敏感相对稳健相对稳健相同值处理不涉及使用平均秩次有专门的修正公式如 tau-b解释性直观解释力强较好对于非专业人士稍难理解计算复杂度O(n)O(n log n) (排序开销)O(n²) (对于大样本较慢)Matlab函数corrcoef,corr(x, y, ‘Type‘, ‘Pearson‘)corr(x, y, ‘Type‘, ‘Spearman‘)corr(x, y, ‘Type‘, ‘Kendall‘)个人经验之谈在探索性数据分析EDA阶段我习惯同时计算皮尔逊和斯皮尔曼系数。如果两者结果差异巨大例如皮尔逊弱相关而斯皮尔曼强相关这本身就是一个强烈的信号提示数据可能存在非线性、非正态或异常值需要进一步深挖。肯德尔τ我更多用在需要与文献方法保持一致或处理明确等级数据时。3. Matlab实战从数据准备到结果可视化理论说得再多不如一行代码。我们用一个模拟的、贴近实际的数据集来贯穿整个实操流程。假设我们正在研究某城市夏季“每日最高气温”与“冰淇淋店销售额”和“泳池入场人数”之间的关系。3.1 数据模拟与预处理首先我们生成一份包含30天记录的数据。为了让案例更真实我故意加入了一些特性销售额与气温基本是线性正相关但有几个异常促销日泳池人数与气温是单调递增但非严格线性例如超过一定温度后人数增长放缓同时数据中存在一些随机噪声。% 清空环境 clear; close all; clc; % 设置随机种子保证可复现 rng(2025); % 模拟数据30天 n_days 30; temperature 25 8 * randn(n_days, 1); % 平均25°C标准差8°C temperature min(max(temperature, 15), 40); % 限制在15-40°C之间 % 1. 冰淇淋销售额基本与温度线性相关但第10天和20天有异常促销 icecream_sales 500 30 * temperature 50 * randn(n_days, 1); icecream_sales(10) icecream_sales(10) 400; % 异常高促销日 icecream_sales(20) icecream_sales(20) - 300; % 异常低可能停电 % 2. 泳池人数与温度呈非线性单调关系对数增长并加入噪声 pool_attendance 200 100 * log(temperature - 14) 30 * randn(n_days, 1); pool_attendance max(pool_attendance, 0); % 确保非负 % 将数据组合成表便于管理 data table(temperature, icecream_sales, pool_attendance, ... VariableNames, {Temperature, IcecreamSales, PoolAttendance}); % 初步查看数据 disp(数据前5行); disp(head(data, 5)); summary(data)生成数据后第一步永远是可视化。我们绘制散点图矩阵来直观感受变量间的关系。% 绘制散点图矩阵与直方图 figure(Position, [100, 100, 900, 700]); plotmatrix([data.Temperature, data.IcecreamSales, data.PoolAttendance]); title(变量间关系散点图矩阵); % 为子图添加标签 ax gcf; ax.Children(9).YLabel.String Temperature (°C); ax.Children(6).YLabel.String Icecream Sales (¥); ax.Children(3).YLabel.String Pool Attendance; ax.Children(7).XLabel.String Temperature (°C); ax.Children(8).XLabel.String Icecream Sales (¥); ax.Children(9).XLabel.String Pool Attendance;通过散点图你应该能观察到气温与销售额大致呈线性但有两个点明显偏离气温与泳池人数呈曲线增长关系。这初步验证了我们选择不同相关性方法的必要性。3.2 三种相关系数的计算与假设检验Matlab中计算相关性主要有两个核心函数corrcoef和corr。corrcoef主要用于快速计算皮尔逊相关系数矩阵。而功能更强大的corr函数则可以指定相关系数类型并返回假设检验的p值。3.2.1 使用corr函数进行综合计算corr函数语法灵活是我们进行相关性分析的主力。% 计算三种相关系数矩阵及对应的p值矩阵 % 皮尔逊 [R_pearson, P_pearson] corr(table2array(data), Type, Pearson); % 斯皮尔曼 [R_spearman, P_spearman] corr(table2array(data), Type, Spearman); % 肯德尔 [R_kendall, P_kendall] corr(table2array(data), Type, Kendall); % 创建一个更美观的显示函数 function displayCorrMatrix(R, P, method, varNames) fprintf(\n %s 相关系数矩阵 \n, method); fprintf(%12s, ); fprintf(%12s, varNames{:}); fprintf(\n); for i 1:size(R, 1) fprintf(%12s, varNames{i}); for j 1:size(R, 2) if i j fprintf(%12s, 1.000); else % 将p值标记在相关系数下方 sig ; if P(i, j) 0.001 sig ***; elseif P(i, j) 0.01 sig **; elseif P(i, j) 0.05 sig *; end fprintf(%8.3f%s, R(i, j), sig); end end fprintf(\n); end fprintf(注* p0.05, ** p0.01, *** p0.001\n); end varNames data.Properties.VariableNames; displayCorrMatrix(R_pearson, P_pearson, 皮尔逊, varNames); displayCorrMatrix(R_spearman, P_spearman, 斯皮尔曼, varNames); displayCorrMatrix(R_kendall, P_kendall, 肯德尔, varNames);运行这段代码你会得到三个清晰的矩阵。对比观察你会发现关键差异气温 vs. 冰淇淋销售额皮尔逊系数可能因为那两个异常点而被拉低或扭曲而斯皮尔曼和肯德尔系数由于基于秩次受异常值影响小更能反映真实的单调正相关趋势。它们的p值很可能更显著。气温 vs. 泳池人数皮尔逊系数衡量线性关系对于这种曲线关系其值会低估两者的关联强度。斯皮尔曼和肯德尔系数捕捉的是单调性因此计算出的相关系数会更接近真实的关联强度。3.2.2 成对变量详细分析示例有时我们需要对特定的一对变量进行深入分析并可视化。% 深入分析 气温(T) 与 泳池人数(P) X data.Temperature; Y data.PoolAttendance; % 1. 计算各种相关系数及p值 [R_pearson, P_pearson] corr(X, Y, Type, Pearson); [R_spearman, P_spearman] corr(X, Y, Type, Spearman); [R_kendall, P_kendall] corr(X, Y, Type, Kendall); fprintf(\n【气温 vs. 泳池人数】详细分析\n); fprintf(皮尔逊 r %.3f, p %.4f\n, R_pearson, P_pearson); fprintf(斯皮尔曼 ρ %.3f, p %.4f\n, R_spearman, P_spearman); fprintf(肯德尔 τ %.3f, p %.4f\n, R_kendall, P_kendall); % 2. 绘制带拟合线的散点图 figure(Position, [100, 100, 1200, 400]); subplot(1, 3, 1); scatter(X, Y, 50, filled, MarkerFaceColor, [0.2 0.6 0.8]); hold on; % 线性拟合皮尔逊相关对应的模型 p polyfit(X, Y, 1); yfit polyval(p, X); plot(X, yfit, r-, LineWidth, 2); xlabel(Temperature (°C)); ylabel(Pool Attendance); title(sprintf(线性拟合 (Pearson r%.3f), R_pearson)); grid on; legend(数据点, 线性拟合, Location, best); subplot(1, 3, 2); scatter(X, Y, 50, filled, MarkerFaceColor, [0.8 0.4 0.2]); hold on; % 绘制一条非参数平滑曲线如lowess体现单调趋势 % 可以使用 smooth 函数 ysmooth smooth(X, Y, 0.3, lowess); % lowess局部加权回归 [sortedX, idx] sort(X); plot(sortedX, ysmooth(idx), g-, LineWidth, 2); xlabel(Temperature (°C)); ylabel(Pool Attendance); title(sprintf(单调趋势 (Spearman ρ%.3f), R_spearman)); grid on; legend(数据点, 平滑曲线, Location, best); subplot(1, 3, 3); % 绘制等级散点图 [~, rankX] sort(X); [~, rankY] sort(Y); scatter(rankX, rankY, 50, filled, MarkerFaceColor, [0.4 0.2 0.6]); hold on; p_rank polyfit(rankX, rankY, 1); yfit_rank polyval(p_rank, rankX); plot(rankX, yfit_rank, m-, LineWidth, 2); xlabel(Temperature Rank); ylabel(Pool Attendance Rank); title(等级散点图 (Spearman/Kendall基础)); grid on; legend(等级点, 等级拟合, Location, best);通过这三张子图的对比你可以直观理解不同系数在度量何种关系。第一张图的直线拟合明显无法完美捕捉数据 pattern导致皮尔逊系数偏低。第二张图的平滑曲线更好地描述了趋势。第三张图的等级散点图则展示了斯皮尔曼相关的计算基础——即使原始关系非线性只要单调等级关系就是线性的。3.3 处理缺失值与“结”Ties真实数据常有缺失。corr函数默认使用‘pairwise‘方式处理缺失值即计算每对变量时只使用在该对上都非缺失的观测。这可能导致不同变量对的相关系数基于不同的样本子集计算需谨慎解读。另一种方式是‘complete‘即删除任何变量上有缺失的整行观测。% 模拟含有缺失值的数据 data_missing data; data_missing.IcecreamSales([5, 15]) NaN; data_missing.PoolAttendance(12) NaN; fprintf(\n 处理缺失值示例 \n); fprintf(原始数据有 %d 行。\n, height(data_missing)); % 1. Pairwise 方式 [R_pw, P_pw] corr(table2array(data_missing), Type, Pearson, Rows, pairwise); fprintf(\nPairwise处理后的相关系数矩阵样本量因变量对而异:\n); disp(R_pw); % 2. Complete 方式 [R_comp, P_comp] corr(table2array(data_missing), Type, Pearson, Rows, complete); fprintf(\nComplete处理后的相关系数矩阵使用完整观测样本量一致:\n); disp(R_comp); fprintf(Complete方式使用的有效样本行数: %d\n, sum(all(~isnan(table2array(data_missing)), 2)));对于斯皮尔曼和肯德尔相关当数据中存在相同的值称为“结”时需要特殊处理。Matlab的corr函数在计算斯皮尔曼和肯德尔系数时已经内置了处理结的算法如对相同值赋予平均秩次。对于肯德尔τ如果数据结很多可以考虑使用‘Kendall‘类型它会自动计算 tau-b 统计量该统计量对结进行了修正。4. 高级应用与结果深度解读计算出相关系数只是开始如何严谨地解读并应用于实际建模才是更见功力的地方。4.1 相关性显著性检验与置信区间我们得到的p值原假设H0通常是“两个变量相关系数为0”。p值 0.05 意味着我们有足够的证据拒绝原假设认为相关性在统计上是显著的。但显著性不代表相关性强度高一个很弱的相关系数如0.1在大样本量下也可能非常显著p值极小。因此报告结果时必须同时给出相关系数值和其置信区间。Matlab统计工具箱提供了corrcoef返回置信区间的功能但对于corr函数我们可以通过自助法Bootstrap来估计。% 使用Bootstrapping估计皮尔逊相关系数的95%置信区间 rng(0); % 重置随机种子 n_boot 1000; % 自助法重采样次数 boot_stat bootstrp(n_boot, (x,y) corr(x,y, Type, Pearson), X, Y); % 计算置信区间百分位数法 ci_lower prctile(boot_stat, 2.5); ci_upper prctile(boot_stat, 97.5); fprintf(\n【气温 vs. 泳池人数】皮尔逊相关系数自助法置信区间\n); fprintf(相关系数估计值 r %.3f\n, R_pearson); fprintf(95%% 置信区间: [%.3f, %.3f]\n, ci_lower, ci_upper); % 绘制自助法抽样分布直方图 figure; histogram(boot_stat, 30, Normalization, pdf, FaceColor, [0.7 0.7 0.9], EdgeColor, k); hold on; xline(R_pearson, r-, LineWidth, 2, DisplayName, 样本估计值); xline(ci_lower, b--, LineWidth, 1.5, DisplayName, 95% CI 下限); xline(ci_upper, b--, LineWidth, 1.5, DisplayName, 95% CI 上限); xlabel(皮尔逊相关系数 (r)); ylabel(概率密度); title(自助法相关系数抽样分布); legend(show); grid on;如果置信区间不包含0则与p值0.05的结论一致认为相关性显著。置信区间还能告诉我们估计的精确度区间越窄估计越精确。4.2 偏相关分析控制混淆变量很多时候两个变量间的相关可能是由第三个变量混淆变量驱动的。例如冰淇淋销售额和泳池人数可能都仅仅是因为气温高而增加它们本身并无直接关系。这时就需要偏相关分析即在控制其他变量如气温的条件下考察两个变量间的净相关。Matlab中可以使用partialcorr函数。% 计算控制“气温”后“冰淇淋销售额”与“泳池人数”的偏相关系数 sales data.IcecreamSales; attendance data.PoolAttendance; temp data.Temperature; % 计算偏皮尔逊相关 [partial_r, partial_p] partialcorr([sales, attendance], temp, Type, Pearson); % partialcorr 输入可以是矩阵这里我们只关心 sales 和 attendance 之间的偏相关 % 实际上我们更常用以下形式 [partial_r_single, partial_p_single] partialcorr(sales, attendance, temp, Type, Pearson); fprintf(\n 偏相关分析 \n); fprintf(控制变量气温后\n); fprintf(冰淇淋销售额 vs. 泳池人数的偏皮尔逊相关 r %.3f, p %.4f\n, partial_r_single, partial_p_single); % 对比一下零阶相关未控制气温 [zero_r, zero_p] corr(sales, attendance, Type, Pearson); fprintf(未控制变量时的零阶皮尔逊相关 r %.3f, p %.4f\n, zero_r, zero_p);如果partial_r远小于zero_r且变得不显著那就说明两者之前的强相关很大程度上是由气温这个共同原因造成的虚假相关。这是一个非常重要的因果推断初步检查步骤。4.3 相关性矩阵可视化热图与聚类当变量很多时例如几十个基因的表达量我们需要一种有效的方式来可视化整个相关性矩阵。热图是绝佳的选择如果再结合层次聚类对变量重新排序可以揭示变量间的潜在分组结构。% 假设我们有一个更大的模拟数据集包含6个变量 rng(5); n_obs 50; var_names {Var1, Var2, Var3, Var4, Var5, Var6}; % 生成一些有相关结构的数据 base randn(n_obs, 1); data_large zeros(n_obs, 6); data_large(:, 1) base 0.3*randn(n_obs,1); % Var1 与 base 强相关 data_large(:, 2) 0.8*base 0.5*randn(n_obs,1); % Var2 与 base 相关 data_large(:, 3) -0.7*base 0.4*randn(n_obs,1); % Var3 与 base 负相关 data_large(:, 4) randn(n_obs, 1); % Var4 独立 data_large(:, 5) 0.6*data_large(:,1) 0.6*randn(n_obs,1); % Var5 与 Var1 相关 data_large(:, 6) randn(n_obs, 1); % Var6 独立 R_large corr(data_large, Type, Spearman); % 绘制热图 figure(Position, [100, 100, 700, 600]); imagesc(R_large); colormap(jet); % 可以使用 parula, hot, coolwarm 等颜色映射 colorbar; caxis([-1, 1]); % 固定颜色轴范围 title(斯皮尔曼相关系数矩阵热图, FontSize, 14); set(gca, XTick, 1:6, XTickLabel, var_names, YTick, 1:6, YTickLabel, var_names); xtickangle(45); % 在方格中添加数值 for i 1:6 for j 1:6 text(j, i, sprintf(%.2f, R_large(i,j)), ... HorizontalAlignment, center, ... Color, ifelse(abs(R_large(i,j))0.5, w, k), ... % 高相关用白字 FontSize, 10); end end % 添加层次聚类树状图 % 使用相关系数距离 (1 - |r|) 或 (1 - r) 等 distance 1 - abs(R_large); % 使用绝对相关系数因为负相关也表示有关联 % 为了聚类需要将距离矩阵转换为向量形式 Z linkage(squareform(distance, tovector), average); % 平均链接法 % 添加树状图 figure(Position, [800, 100, 600, 500]); dendrogram(Z, Labels, var_names, Orientation, left); title(基于相关系数距离的变量聚类树状图); xlabel(距离 (1 - |r|));通过热图我们可以快速识别出强正相关红色、强负相关蓝色和弱相关绿色/黄色的变量对。聚类树状图则能帮助我们将行为相似的变量归组为后续的降维如主成分分析或特征选择提供指导。5. 常见陷阱、误区与实战心得走过不少弯路后我总结了一些在相关性分析中容易犯的错误和需要注意的要点。5.1 误区一将相关性等同于因果性这是数据分析中最经典的错误但永远值得反复强调。相关系数再高也只能说明两个变量协同变化绝不能证明是其中一个导致了另一个。可能有第三变量混淆变量驱动两者也可能存在反向因果或纯粹的巧合。例如我们发现“冰淇淋销售额”和“溺水事故数”高度正相关但显然不是冰淇淋导致溺水而是共同的“夏季高温”和“游泳人数增加”在起作用。在做任何结论前务必从逻辑和领域知识出发思考可能的因果链条并尝试用偏相关或更复杂的模型如结构方程模型来控制潜在混淆因素。5.2 误区二忽视数据的分布与异常值如前所述皮尔逊相关对非正态和异常值极其敏感。在计算皮尔逊相关系数之前进行正态性检验如Jarque-Bera检验、Q-Q图和异常值检测如箱线图、3σ原则是标准流程。如果数据严重偏离正态或存在有影响力的异常点斯皮尔曼或肯德尔相关是更安全的选择。一个快速检查的方法是同时计算皮尔逊和斯皮尔曼系数如果差异很大就需要警惕。5.3 误区三样本量过小或存在极端值相关系数的稳定性依赖于样本量。样本量很小时如n10即使计算出的相关系数很大也可能由于随机波动导致不显著或者置信区间非常宽。反之在大样本量如n1000下即使非常微弱的相关系数如0.05也可能具有统计显著性p值很小。此时应更关注相关系数的实际大小效应量而非仅仅p值。一个|r|0.05的相关性虽然统计显著但实际意义可能微乎其微。5.4 实操心得流程化检查清单为了确保分析质量我为自己制定了一个简单的检查清单可视化先行永远先画散点图矩阵观察关系形态、异常值、非线性模式。正态性判断对关键连续变量做正态性检验或查看Q-Q图。方法选择线性正态无异常值 → 皮尔逊。单调非正态/有异常值/等级数据 → 斯皮尔曼。等级数据较多相同值/关注秩序一致性 → 肯德尔。不确定时同时计算皮尔逊和斯皮尔曼作为对比。结果报告报告相关系数值、p值或显著性标记以及置信区间。对于重要结论考虑用自助法验证。因果审慎思考并尝试排除混淆变量偏相关结合领域知识解读绝不轻言因果。代码可复现像本文示例一样在脚本开头使用rng固定随机种子确保每次运行结果一致。5.5 性能考量大数据集下的计算当变量数量成千上万时如基因芯片数据计算整个相关性矩阵可能非常耗时尤其是O(n²)复杂度的肯德尔相关。此时可以使用corr函数的矩阵输入形式利用Matlab的向量化优化。如果只需要计算特定变量对的相关性避免计算整个大矩阵。对于超大规模数据可以考虑抽样计算或使用专门为大数据设计的近似算法库。斯皮尔曼相关由于需要排序在大数据下也可能成为瓶颈需权衡利弊。最后记住相关性分析是强大的探索性工具但它只是数据分析故事的开篇。它指引方向揭示线索但构建坚实可靠的模型和结论还需要回归、机器学习等更多方法的配合。希望这篇结合了原理、Matlab实战与经验心得的指南能让你下次面对数据时在选择和解读相关性分析方法上更加得心应手。
返回列表