公司动态
MATLAB与R语言描述性分析实战:数据建模前的关键探索
1. 从数据到洞察为什么描述性分析是建模的基石如果你刚接触数据分析或者数学建模可能会被各种复杂的算法和模型搞得眼花缭乱。神经网络、随机森林、支持向量机……这些听起来高大上的名词往往让人恨不得立刻上手用它们来解决手头的问题。但在我十多年的建模经历里见过太多新手甚至是有一定经验的朋友都栽在了一个看似简单、实则至关重要的环节上——描述性分析。很多人拿到数据草草看一眼平均值就迫不及待地开始构建模型结果模型效果不佳或者得出的结论与常识相悖却找不到原因。描述性分析就是建模前的“望闻问切”。它不直接告诉你“为什么”但它能清晰地告诉你“是什么”。通过一系列统计量和可视化手段它帮你全面、客观地认识你的数据数据的分布形态如何有没有异常值变量之间是否存在关联数据的尺度是否统一这些问题如果不搞清楚直接上模型无异于在迷雾中射击命中目标全靠运气。MATLAB和R语言作为两大科学计算与统计分析的利器在描述性分析上各有千秋。MATLAB以其强大的矩阵运算和丰富的工具箱在工程和信号处理领域备受青睐而R语言则因其在统计领域的深厚积淀和庞大的社区生态成为统计学家和数据科学家的首选。本文将结合这两种工具手把手带你掌握描述性分析的核心技能为后续的建模工作打下坚实、可靠的基础。2. 描述性分析工具箱核心统计量与可视化方法全解析描述性分析的核心任务可以概括为两个方面一是用数字统计量概括数据特征二是用图形可视化直观展示数据形态。两者相辅相成缺一不可。单纯看数字容易陷入抽象单纯看图则可能忽略精确的量化关系。2.1 核心统计量数据的“数字画像”统计量是我们量化描述数据分布特征的尺子。主要分为以下几类2.1.1 集中趋势度量数据围绕哪里聚集这回答了“典型值”是什么的问题。均值 (Mean)所有数据之和除以数据个数。这是最常用的指标但它对极端值异常值非常敏感。一个亿万富翁走进房间会瞬间拉高所有人的平均收入。中位数 (Median)将数据从小到大排序后位于中间位置的值。它对异常值不敏感能更好地反映数据的“中心”。当数据分布偏斜时中位数比均值更有代表性。众数 (Mode)数据中出现次数最多的值。主要用于分类数据也能用于连续数据帮助发现多峰分布。2.1.2 离散程度度量数据有多“散”这回答了数据波动性的大小。方差 (Variance) 和标准差 (Standard Deviation)衡量数据点与均值的平均偏离程度。标准差是方差的平方根与原始数据单位一致更常用。标准差越大数据越分散。极差 (Range)最大值与最小值之差。计算简单但同样极易受异常值影响。四分位距 (Interquartile Range, IQR)第三四分位数 (Q3) 与第一四分位数 (Q1) 之差即IQR Q3 - Q1。它描述了中间50%数据的分布范围对异常值稳健是识别异常值的核心依据通常将小于Q1 - 1.5*IQR或大于Q3 1.5*IQR的值视为异常值。2.1.3 分布形态度量数据长什么样这描述了数据分布的形状。偏度 (Skewness)衡量分布不对称性的程度。偏度 0右偏正偏均值 中位数有一条长尾伸向右侧大值方向。偏度 0左偏负偏均值 中位数有一条长尾伸向左侧小值方向。偏度 ≈ 0分布大致对称。峰度 (Kurtosis)衡量分布曲线顶峰的尖峭程度和尾部厚度。通常与标准正态分布峰度3有些软件定义为0比较。峰度 3 (或 0)比正态分布更尖峭、尾部更厚更多极端值。峰度 3 (或 0)比正态分布更平缓、尾部更薄。2.2 核心可视化让数据自己“说话”图形能瞬间传递大量信息是发现模式、异常和关系的利器。2.2.1 单变量可视化看清每一个变量的真面目直方图 (Histogram)展示连续变量的分布情况通过划分区间箱并计数直观显示数据集中在哪些区间。箱数的选择会影响图形解读需要尝试调整。箱线图 (Boxplot)基于五数概括最小值、Q1、中位数、Q3、最大值展示数据分布尤其擅长突出显示异常值在图形中常以独立点表示。核密度估计图 (Kernel Density Estimation, KDE)直方图的“平滑版”用连续曲线估计变量的概率密度函数能更流畅地展示分布形状。2.2.2 双变量及多变量可视化探索变量间的“关系网”散点图 (Scatter Plot)研究两个连续变量之间相关性的最基本、最有效的图形。可以添加趋势线如线性回归线来辅助判断。相关矩阵热图 (Correlation Matrix Heatmap)当变量较多时用颜色深浅表示每对变量之间的相关系数如皮尔逊相关系数快速定位强相关或强负相关的变量对。分组箱线图/小提琴图 (Grouped Boxplot/Violin Plot)用于比较一个连续变量在不同类别分类变量下的分布差异。小提琴图结合了箱线图和核密度估计能展示更丰富的分布信息。3. MATLAB实战以汽车数据集为例的完整分析流程我们以MATLAB自带的carsmall数据集为例它包含了100辆汽车的各类信息。假设我们正在为一个汽车油耗预测模型做准备描述性分析是我们的第一步。3.1 数据导入与初步探查首先我们加载数据并看看它的基本情况。% 加载数据 load carsmall % 将变量转换为更易处理的表格格式 data table(MPG, Cylinders, Displacement, Horsepower, Weight, Acceleration, Model_Year, Origin); data.Origin categorical(cellstr(Origin)); % 将Origin转换为分类变量 % 查看数据前几行和基本信息 head(data) summary(data)summary函数会输出每个变量的概要类型、缺失值数量、以及对于数值变量会给出最小值、最大值、中位数、均值等。这是我们接触数据的第一次“握手”。3.2 单变量分析深入审视每一个特征3.2.1 数值型变量分析我们重点关注油耗MPG、马力Horsepower和车重Weight。figure(Position, [100, 100, 1200, 400]) % 子图1MPG的直方图与核密度估计 subplot(1,3,1) histogram(data.MPG, Normalization, pdf, FaceColor, [0.2 0.6 0.8], EdgeColor, none); hold on [f, xi] ksdensity(data.MPG); plot(xi, f, r-, LineWidth, 2); xlabel(MPG); ylabel(概率密度); title(MPG分布直方图KDE); grid on; legend(直方图, 核密度估计); % 子图2Horsepower的箱线图 subplot(1,3,2) boxplot(data.Horsepower, Labels, {马力}, Colors, k); ylabel(Horsepower); title(马力分布箱线图); % 手动计算并标注异常值 Q prctile(data.Horsepower, [25 50 75]); IQR Q(3) - Q(1); lowerBound Q(1) - 1.5*IQR; upperBound Q(3) 1.5*IQR; outliers data.Horsepower(data.Horsepower lowerBound | data.Horsepower upperBound); text(ones(size(outliers))*1.1, outliers, num2str(outliers), VerticalAlignment,middle); % 子图3计算并展示关键统计量 subplot(1,3,3) axis off stats_txt { sprintf(变量: MPG, Horsepower, Weight); sprintf(均值: %.2f, %.2f, %.2f, mean(data.MPG,omitnan), mean(data.Horsepower,omitnan), mean(data.Weight,omitnan)); sprintf(中位数: %.2f, %.2f, %.2f, median(data.MPG,omitnan), median(data.Horsepower,omitnan), median(data.Weight,omitnan)); sprintf(标准差: %.2f, %.2f, %.2f, std(data.MPG,omitnan), std(data.Horsepower,omitnan), std(data.Weight,omitnan)); sprintf(偏度: %.2f, %.2f, %.2f, skewness(data.MPG), skewness(data.Horsepower), skewness(data.Weight)); sprintf(峰度: %.2f, %.2f, %.2f, kurtosis(data.MPG), kurtosis(data.Horsepower), kurtosis(data.Weight)); }; text(0.1, 0.5, stats_txt, FontSize, 10, VerticalAlignment, middle); title(关键描述性统计量);通过这个分析我们可能发现MPG的分布略微左偏可能有少数极高油耗的车马力存在明显的异常高值高性能车车重的标准差很大车型差异大。这些观察直接影响后续处理是否处理异常值是否对偏斜数据做变换3.2.2 分类变量分析查看气缸数Cylinders和产地Origin的分布。figure(Position, [100, 100, 800, 400]) subplot(1,2,1) histogram(categorical(data.Cylinders), FaceColor, [0.8 0.4 0.2]); xlabel(气缸数); ylabel(频数); title(气缸数分布); subplot(1,2,2) pie(countcats(data.Origin), categories(data.Origin)); title(汽车产地分布);这告诉我们数据集中四缸、六缸、八缸车的比例以及美国、欧洲、日本车的比例。这对于理解数据代表性和后续可能的分组分析至关重要。3.3 双变量关系探索寻找预测线索油耗预测模型中马力、车重与油耗的关系是核心。figure(Position, [100, 100, 1000, 400]) % 子图1MPG vs Horsepower 散点图 subplot(1,2,1) scatter(data.Horsepower, data.MPG, 40, filled, MarkerFaceAlpha, 0.6); xlabel(Horsepower); ylabel(MPG); title(马力与油耗关系); % 添加线性趋势线 hold on p polyfit(data.Horsepower(~isnan(data.Horsepower) ~isnan(data.MPG)), ... data.MPG(~isnan(data.Horsepower) ~isnan(data.MPG)), 1); xfit linspace(min(data.Horsepower), max(data.Horsepower), 100); yfit polyval(p, xfit); plot(xfit, yfit, r-, LineWidth, 2); legend(数据点, 线性趋势, Location, best); grid on % 子图2MPG vs Weight 散点图按气缸数着色 subplot(1,2,2) gscatter(data.Weight, data.MPG, data.Cylinders); xlabel(Weight); ylabel(MPG); title(车重与油耗关系按气缸数着色); legend(Location, best); grid on散点图清晰显示马力越大、车重越重油耗通常越高MPG越低且呈现明显的负相关关系。按气缸数着色后我们发现八缸车红色普遍集中在右下角重、高油耗而四缸车蓝色多在左上角轻、低油耗。这提示“气缸数”可能是一个重要的分类特征或者与马力、车重存在共线性。3.4 多变量关系初探相关矩阵热图当变量更多时我们需要一个全局视图。% 选择数值型变量 numericVars data(:, {MPG, Cylinders, Displacement, Horsepower, Weight, Acceleration}); % 计算皮尔逊相关系数矩阵并处理缺失值成对删除 corrMatrix corr(table2array(numericVars), Rows, pairwise); % 绘制热图 figure heatmap(corrMatrix, XData, numericVars.Properties.VariableNames, ... YData, numericVars.Properties.VariableNames, ... Colormap, parula, ColorbarVisible, on, ... Title, 数值变量相关系数矩阵);热图一目了然地显示MPG与Weight、Horsepower、Displacement、Cylinders有强负相关而Weight、Horsepower、Displacement、Cylinders彼此之间强正相关。这证实了我们的猜测这些发动机和车身尺寸变量高度共线在后续建模时如线性回归可能需要考虑只选取其中一个或使用主成分分析PCA进行降维以避免多重共线性问题。实操心得MATLAB的table数据类型强烈建议将数据转为table格式。它支持列名操作如data.MPG能混合存储不同类型数据并且与许多统计函数如grpstats兼容性更好。使用summary(table)可以快速获得一份非常专业的变量概览报告是探索性数据分析EDA的高效起点。4. R语言实战同一分析另一种哲学与工具链R语言在描述性分析上拥有极其丰富和专业的包。我们使用ggplot2进行可视化用dplyr进行数据操作并用psych包生成详细的描述性统计报告。我们使用R内置的mtcars数据集它与MATLAB的carsmall类似。4.1 环境准备与数据加载# 安装必要的包如果尚未安装 # install.packages(c(ggplot2, dplyr, psych, corrplot, GGally)) # 加载库 library(ggplot2) library(dplyr) library(psych) library(corrplot) library(GGally) # 加载并查看数据 data(mtcars) head(mtcars) str(mtcars) # 为方便起见将一些数值变量转为因子分类变量 mtcars$cyl - as.factor(mtcars$cyl) mtcars$vs - as.factor(mtcars$vs) mtcars$am - as.factor(mtcars$am) mtcars$gear - as.factor(mtcars$gear) mtcars$carb - as.factor(mtcars$carb)4.2 使用psych包快速生成综合统计报告R的psych包的describe()函数非常强大。# 选择我们关心的连续变量 continuous_vars - mtcars %% select(mpg, disp, hp, drat, wt, qsec) # 生成描述性统计报告 desc_stats - describe(continuous_vars, fast FALSE) # fastFALSE 会计算偏度峰度 print(desc_stats)这份报告一次性给出了变量数、均值、标准差、中位数、截尾均值、绝对中位差、最小值、最大值、范围、偏度、峰度等。效率远超手动计算。4.3 基于ggplot2的精细化可视化ggplot2的图层语法提供了无与伦比的灵活性和美观度。4.3.1 单变量分布组合图# 绘制mpg油耗的分布组合图直方图密度曲线箱线图 p1 - ggplot(mtcars, aes(x mpg)) geom_histogram(aes(y ..density..), bins 15, fill steelblue, alpha 0.7, color black) geom_density(color red, linewidth 1) geom_boxplot(aes(x 10, y mpg), width 5, outlier.color darkred, outlier.size 3) # 将箱线图放在顶部 labs(title 油耗 (mpg) 分布分析, x Miles/(US) gallon, y 密度) theme_minimal() print(p1)4.3.2 分组比较与关系探索# 按气缸数(cyl)分组的油耗(mpg)箱线图与小提琴图 p2 - ggplot(mtcars, aes(x cyl, y mpg, fill cyl)) geom_violin(alpha 0.5, trim FALSE) geom_boxplot(width 0.2, alpha 0.8, outlier.shape NA) stat_summary(fun mean, geom point, shape 18, size 4, color black) # 添加均值点 labs(title 不同气缸数下的油耗分布, x 气缸数, y Miles/(US) gallon) theme_minimal() theme(legend.position none) print(p2) # 散点图矩阵快速查看多个变量间关系 pairs_plot - ggpairs(mtcars %% select(mpg, wt, hp, qsec), lower list(continuous wrap(smooth, method lm, se FALSE, alpha 0.3)), diag list(continuous wrap(barDiag, bins 10)), upper list(continuous wrap(cor, size 5))) print(pairs_plot)ggpairs来自GGally包它能生成一个矩阵图对角线是每个变量的分布下三角是散点图可添加平滑曲线上三角是相关系数。这是探索性数据分析的神器。4.3.3 相关矩阵的高级可视化# 计算相关系数矩阵 cor_matrix - cor(mtcars %% select(mpg, disp, hp, drat, wt, qsec)) # 使用corrplot包绘制 corrplot(cor_matrix, method color, type upper, order hclust, tl.col black, tl.srt 45, addCoef.col black, title 变量相关矩阵 (层次聚类排序))corrplot提供了丰富的相关矩阵可视化方法order hclust参数能根据层次聚类结果重新排列变量使得相关性模式区块更加清晰。R语言实操心得管道操作符%%与dplyrdplyr包的管道操作符%%让数据操作流程变得极其清晰和可读。它的逻辑是“然后”数据 %% 操作1() %% 操作2()。例如mtcars %% filter(cyl 4) %% select(mpg, hp) %% summarise(avg_mpg mean(mpg))意思是“取mtcars数据然后筛选出cyl为4的行然后选择mpg和hp列然后计算mpg的平均值”。这种链式操作大大提升了代码的编写效率和可维护性。5. 从分析到决策描述性结果的建模前指导描述性分析不是终点而是建模的决策依据。基于前面的分析我们可以形成一系列具体的预处理和建模策略。5.1 数据清洗与预处理方案缺失值处理在carsmall数据中Horsepower有少量缺失。我们之前用‘omitnan’参数跳过了它们。在正式建模前需要决定是删除这些样本还是用均值、中位数或基于其他变量的回归方法来填补。箱线图帮助我们定位了这些缺失值是否处于异常位置。异常值处理马力Horsepower的箱线图显示存在高异常值。需要结合业务判断这些是错误数据需要修正/删除还是合理的高性能车数据需要保留如果保留考虑到许多模型如线性回归、K均值聚类对异常值敏感可能需要使用对异常值稳健的模型如决策树、随机森林或对变量进行变换如取对数来减弱其影响。数据变换如果发现变量如车重Weight的分布严重偏斜或者为了满足模型的假设如线性回归的正态性假设可能需要进行对数变换、平方根变换或Box-Cox变换。5.2 特征工程与选择启示特征选择相关矩阵热图明确显示Cylinders,Displacement,Horsepower,Weight高度相关。这意味着它们携带了大量重复信息。在构建线性回归模型预测MPG时全部放入会导致多重共线性使系数估计不稳定。我们可以领域知识驱动选择最具物理意义或最容易解释的一个如Weight。计算衍生特征例如计算功率重量比 (Horsepower/Weight) 作为一个新特征它可能比单独两个特征更具预测力。使用降维技术对这几个高度相关的变量进行主成分分析PCA用生成的主成分作为新特征。交互项探索散点图中按Cylinders着色显示不同组别下Weight和MPG的关系可能不同。这提示我们在模型中加入Cylinders和Weight的交互项 (Cylinders * Weight) 可能会提升模型表现因为它捕捉了“对于不同气缸数的车车重对油耗的影响程度不同”这一现象。5.3 模型选型初步指向关系非线性MPG与Horsepower的散点图可能显示轻微的非线性曲线关系。单纯的线性回归可能不够需要考虑多项式回归、或使用广义加性模型GAM、支持向量回归SVR等能捕捉非线性的模型。异方差性检查观察MPG与Weight的散点图残差的方差是否随着Weight增大而改变如果存在异方差性普通最小二乘回归的估计效率会降低可能需要加权最小二乘法或对因变量进行变换。5.4 分析报告与沟通要点一份好的描述性分析报告不仅是技术文档更是沟通工具。你需要向项目伙伴或业务方清晰地传达数据质量“数据基本完整仅在马力字段有3个缺失已评估并计划用中位数填补。发现2个马力异常高值经确认为正确数据代表高性能车型予以保留但将在建模时关注其影响。”关键发现“油耗与车重、马力呈强负相关。发动机排量、气缸数、马力、车重这四个指标高度共线建议在初步模型中只选用车重作为代表以避免多重共线性问题。”下一步建议“建议进行两项工作第一尝试对车重取对数以改善其分布偏态第二在线性模型中加入气缸数与车重的交互项以捕捉不同车型的差异效应。”描述性分析就像航海家的海图和罗盘它不会自动带你到达目的地但能让你看清自己身处何方暗礁在哪里风向如何从而做出最明智的航行决策。跳过这一步你的建模之旅很可能从一开始就偏离了航线。掌握MATLAB和R这两套工具你就能更从容、更专业地完成这项奠基性工作让后续的复杂模型建立在坚实可靠的数据理解之上。