资讯动态

描述统计进阶:分位数、偏度峰度与相关分析及Python实现

发布时间:2026/10/16 23:27:09 来源:尧图企业网站定制
1. 为什么描述统计的“下半场”才是分水岭如果你刚开始接触数据挖掘可能已经把“均值、中位数、众数、极差、方差、标准差”这些词背得滚瓜烂熟。但真拿到一份几千行的业务数据你想从里面挖出点有价值的信息时光靠这些“上半场”的指标往往不够用。均值会被极端值带偏方差只能告诉你数据“乱不乱”却说不清到底是往哪边乱、乱成什么形状更看不到两个字段之间是不是在暗暗联动。描述统计的“下半场”就是专门补这些窟窿的。这篇文章默认你已经理解描述统计里的基础概念所以直接从分位数、四分位距、偏度、峰度、协方差和相关系数讲起最后用一段Python代码把这些指标一次性算出来。适合正在学数据挖掘、机器学习数学基础或者准备做特征工程但总被各种统计量绕晕的同学。看完你至少能回答三个以前容易含糊的问题数据分布的尾巴在哪边高尖峰到底意味着什么两个变量之间的相关性怎么才算靠谱有朋友可能会问数据挖掘不是靠算法模型说话吗为什么还要回头抠这些统计量实际上你在做探索性数据分析EDA时第一件事就是把每个字段的分布形状、离散程度、相互关系摸清楚。描述统计的“下半场”就是给你提供一套通用的“体检指标”让你在建模前就知道哪些字段可能需要变换、哪些字段高度冗余、哪些字段可能有异常样本。这些判断直接影响特征工程和模型效果可以说是“看得见的算法前戏”。2. 分位数与四分位距把“分布”真正摊开看2.1 分位数到底怎么算、怎么用分位数这个概念通俗讲就是把一组数据按从小到大的顺序排队然后切成若干等份。第p百分位数就是指至少有p%的数据小于等于这个值同时至少有(100-p)%的数据大于等于这个值。最有名的三个分位数是四分位数分别把数据切成四段Q1第25百分位数排在队伍四分之一处的值也叫下四分位数。Q2第50百分位数其实就是中位数队伍正中间的位置。Q3第75百分位数排在四分之三处的值也叫上四分位数。但“排在四分之一处”这句话听起来简单实际操作时有个细节很磨人当数据量不是4的倍数时Q1和Q3到底取哪个位置的数比如有10个样本从小到大排完序25%的位置在2.5你是取第2个还是第3个还是两者平均不同的统计软件会给出不同答案。常见的计算方法有“最近位置法”“线性插值法”Python的numpy默认用的是线性插值pandas的describe底层其实也在做类似的事。不同方法算出的分位数可能略有差异但不会影响对数据分布的整体判断。你在自己的项目里只要固定同一个库别混着算就行。分位数在实际工作中最大的价值在于“抗异常值”。均值被一个极端值拉高几倍时中位数可能纹丝不动Q1和Q3也基本稳定。所以当你需要描述“典型用户”的消费水平、响应时间、存款余额这类容易出长尾的数据时分位数往往比均值靠谱得多。我常用的套路是输出Q1、中位数、Q3和P90、P99这样既能看出主体分布区间又能捕捉极端值的存在。2.2 四分位距与箱线图异常值识别四分位距IQRInterquartile Range就是Q3减去Q1它衡量的是数据中间50%的跨度。相比标准差IQR对异常值更稳健因为Q1和Q3本身就不容易被少数极端数撼动。在特征工程里IQR最经典的用途是画箱线图和检测异常值。箱线图大家应该都见过一个矩形盒子上下边分别是Q1和Q3盒子中间横线是中位数从盒子上下边缘向外伸出两条“须”。很多教学资料里会把须的端点标成最大值和最小值但严格的专业画法里须的端点默认是“合理范围”的边界具体边界是这样算的下边界 Q1 - 1.5 * IQR上边界 Q3 1.5 * IQR超出这个范围的点会被单独画成散点也就是我们常说的“疑似异常值”。1.5这个系数是经验值不是数学真理。你可以根据业务场景把它调成3那样检测出来的异常值更少、更极端。如果你的数据分布接近正态分布用1.5倍IQR大概会标记出约0.7%的数据点这是一个相对灵敏但不会太夸张的比例。真实项目中我遇到过一个典型场景某电商活动的订单金额字段大多数人消费在50到200元之间但偶尔出现几笔上万元的订单。直接用均值统计会得出“平均消费580元”这种看着还行、实则毫无代表性的结论。画个箱线图IQR能清晰告诉你主流消费区间是50到200元那几笔大额订单则被独立展示出来。这时候你就要决策是保留它们做高价值用户分析还是当作异常数据先剔除避免污染后续模型。3. 偏度与峰度读数据形态的进阶指标3.1 偏度数据尾巴朝哪边偏度Skewness用来衡量数据分布是否对称。偏度等于0意味着分布左右对称大于0叫正偏或右偏意思是右侧有一条长长的尾巴多数数据挤在左侧小于0叫负偏或左偏尾巴拖在左侧。这里特别容易记反我自己也翻过车。有个笨办法看尾巴在哪边就是哪边偏。尾巴在右边就是右偏偏度值为正。为什么数据挖掘里这么在意偏度因为很多模型的假设条件里包含“特征近似正态分布”。比如线性回归虽然对特征分布没有硬性要求但某些正则化方法、距离类算法在数据尺度很不均匀时表现会变差。更现实的问题是强偏态分布会让模型难以学到少数极端样本的模式。我们在做特征工程时经常对右偏严重的字段做对数变换、平方根变换或Box-Cox变换目的就是把长尾巴往里收一收让分布更接近对称。判断偏度是否“值得处理”我习惯看绝对值小于0.5基本可视为轻微偏斜0.5到1是中等偏斜超过1就属于严重偏斜。当然这只是经验阈值具体还要结合样本量。样本量很大的时候哪怕偏度只有0.2经过假设检验也可能被判定为“显著偏斜”但那种差异往往没有实际业务影响。别只盯着P值要回到业务场景里看分布是否符合预期。3.2 峰度胖尾巴才是重点峰度Kurtosis是另一个被普遍误解的指标。很多人看到“峰”字以为它描述的是分布顶部有多尖于是脱口而出“峰度越大越尖”。这话不完全对。峰度真正衡量的是分布尾部的厚重程度也就是数据中出现极端值的概率有多大。标准正态分布的峰度为3为了使用方便很多软件会默认输出“超额峰度”Excess Kurtosis也就是把标准正态的3减掉让正态分布的超额峰度变成0。超额峰度大于0表示尾部比正态分布更厚极端值出现概率更高小于0尾部更薄数据更有“截断感”。至于顶部是尖还是平其实只是这个过程的伴生现象。长尾分布为了让总面积保持为1通常会把中间部分“垫高”一些所以看起来更尖。但真正影响你要不要做异常值处理、要不要选稳健模型的是尾部厚不厚而不是尖不尖。我记得某次分析一个支付系统的单笔交易金额时数据的偏度很接近0看起来像个对称分布但超额峰度高达12。当时团队里有人觉得数据形态挺好的可以直接进模型。我坚持先画了Q-Q图果然正态性检验没通过实际上就是比正态分布多了不少极端值。后来对极端值单独做了一轮处理模型在验证集上的表现才稳定下来。这段经历让我养成了一个习惯每次做EDA偏度、峰度必须一起看一个管对称一个管尾巴缺一不可。4. 协方差与相关系数开始打量“关系”4.1 协方差方向和量纲描述统计做到这一步你手里的数据已经不再是一维数组而是带着多个字段的表格。我们很自然想知道这个字段变大时那个字段是跟着变大还是变小或者根本各走各的。这就是两个变量之间“关系”的问题第一个工具叫协方差。协方差的计算原理不复杂就是把两个变量各自的中心化值乘起来再平均。如果两个变量经常同向变动乘积多为正协方差就是正的如果经常反向变动乘积多为负协方差就是负的如果变动方向没什么一致性正负相抵协方差接近0。但协方差有个让人头疼的毛病它受量纲影响很大。比如用“元”计算订单金额和用“分”计算订单金额协方差会相差100倍。如果你因此觉得“这两个变量关系更密切了”那完全是被单位忽悠了。所以在实际工作中我很少直接看协方差的具体数值更多只是用它作为中间结果继续算相关系数。4.2 皮尔逊相关系数与实战注意点皮尔逊相关系数可以理解为把协方差做了“标准化”处理除以两个变量各自的标准差结果被压缩到-1到1之间。1表示完全正相关-1表示完全负相关0表示没有线性相关关系。这是数据挖掘中最常用的相关性指标没有之一。使用时有几个容易踩的坑必须先说清楚。第一皮尔逊相关系数只度量“线性关系”两个变量即使存在很强的非线性关系比如y x²相关系数也可能接近0。第二它对异常值极度敏感。我之前跑过一个收入与消费的数据集原始相关系数是0.35看起来相关性一般后来发现有一条记录收入填错了多了两个0删掉这条后相关系数直接变成0.72。所以算相关之前最好先做异常值筛查。第三相关系数不为0并不代表“有因果关系”只能说明存在统计上的关联。至于谁导致谁需要靠实验设计或更专业的因果推断方法。当数据不是连续变量或者关系不是线性的时候皮尔逊相关系数会不太可靠。这时候可以退一步用斯皮尔曼秩相关系数它计算的是两个变量排序后的相关性不要求原始数据满足正态分布对异常值也更稳健适合处理序数型变量或明显非线性但单调的关系。我在做特征筛选时会把皮尔逊和斯皮尔曼都算出来放在一张表里对比。两者差异很大说明数据里可能存在强异常值或非线性关系就要特别留意。5. 用Python快速落地描述统计5.1 最常用的几个函数理论讲够了直接上实操。Python的pandas、numpy和scipy是计算描述统计量最顺手的工具。日常工作中我最常用的组合是df.describe()一行输出计数、均值、标准差、最小值、Q1、中位数、Q3、最大值。df.quantile(q[0.25, 0.5, 0.75, 0.9, 0.99])自定义任意分位数。df.skew()和df.kurt()分别计算偏度和超额峰度。df.cov()和df.corr()计算协方差矩阵和相关系数矩阵。scipy.stats.spearmanr计算斯皮尔曼相关系数。有一件事必须牢记pandas默认的std()用的是样本标准差分母为n-1numpy的std()默认用的是总体标准差分母为n。如果你从两个库各取一次标准差发现数值对不上先别怀疑算错了多半是自由度设置不同。正确做法是统一使用numpy.std(df, ddof1)或者干脆都交给pandas处理。5.2 一份可直接跑的示例代码假设我们有1000条用户数据字段包括“年龄”“年收入元”“月均消费元”我用一个随机数种子保证可复现然后一次性把上面提到的所有描述统计量算出来。import pandas as pd import numpy as np import scipy.stats as stats # 模拟一份用户数据随机种子保证结果可复现 np.random.seed(42) n 1000 age np.random.normal(35, 10, n).astype(int) income np.random.lognormal(mean10, sigma0.6, sizen) # 右偏的收入分布 expense income * np.random.uniform(0.1, 0.5, n) df pd.DataFrame({ 年龄: age, 年收入: income, 月均消费: expense }) # 基础描述统计 desc df.describe().T print(基础描述统计) print(desc[[mean, std, min, 25%, 50%, 75%, max]]) # 自定义分位数 quantiles df.quantile(q[0.25, 0.5, 0.75, 0.9, 0.99]) print(\n自定义分位数) print(quantiles) # IQR 与异常值个数 Q1 df.quantile(0.25) Q3 df.quantile(0.75) IQR Q3 - Q1 outlier_cond (df Q1 - 1.5 * IQR) | (df Q3 1.5 * IQR) print(\n各字段疑似异常值数量) print(outlier_cond.sum()) # 偏度与峰度 print(\n偏度) print(df.skew()) print(\n超额峰度) print(df.kurt()) # 相关系数矩阵 print(\n皮尔逊相关系数矩阵) print(df.corr()) # 斯皮尔曼相关系数 spearman_corr, spearman_p stats.spearmanr(df) print(\n斯皮尔曼相关系数矩阵) print(spearman_corr) # 变异系数标准差/均值比较不同量纲字段的离散程度 cv df.std() / df.mean() print(\n变异系数) print(cv)上面这段代码跑完之后你会得到一套完整的“数据体检报告”。年收入因为是lognormal分布偏度一般会大于1你可以对比看它在做特征工程时是不是需要做对数变换月均消费和年收入的皮尔逊相关系数通常会很高因为它们本来就是从同一个随机过程中生成的这也提醒你相关性强不等于有独立预测价值两个字段重复度过高时模型里留一个往往就够了。5.3 分组描述统计不要只看整体做数据挖掘时整体统计量往往会把不同分组的差异“抹平”。比如全量用户的平均月消费是300元但新用户可能只有100元老用户却有600元。只看整体你会以为大家都差不多于是模型对用户分群不敏感效果自然上不去。pandas里用groupby配合agg就能快速得到分组描述统计# 给用户随意分一个体验组和对照组 df[分组] np.where(np.random.rand(n) 0.5, 体验组, 对照组) # 按分组计算多个统计量 group_stats df.groupby(分组)[月均消费].agg( 样本量count, 均值mean, 中位数median, 标准差std ) print(group_stats)这个操作在特征工程和A/B分析里几乎是标配。它能帮你快速发现哪些组的分布差异明显哪些组的样本量不足以做可靠分析。配合我之前讲的IQR还能进一步写出“分组异常值识别”的逻辑判断不同组的异常阈值是不是该分别设定。6. 实操中的坑与排查技巧6.1 样本方差分母“n-1”的坑这个坑几乎每个新手都踩过一遍。你用一个numpy公式手算方差跟pandas输出对不上第一反应是数据有问题第二反应是库有Bug。其实都不是只是“样本方差”和“总体方差”的定义不同。样本用n-1做分母是为了用样本估计总体方差时不至于系统性偏小这叫贝塞尔校正。pandas的var()和std()默认就是样本版本numpy为了追求通用性默认是总体版本。解决方案很简单用numpy时明确加上ddof1# 等价于 pandas 的 std() np.std(df[年收入], ddof1)6.2 异常值对描述统计的“污染”异常值对均值、标准差、协方差、皮尔逊相关的影响都很大但对中位数、四分位距、斯皮尔曼相关影响很小。所以排查数据时我习惯先算一套“稳健版”的描述统计中位数、IQR、Q1/Q3、斯皮尔曼相关。如果这套指标和普通指标结论差距明显就先停下来检查数据里是不是有脏数据而不是急着建模。否则你辛辛苦苦训练出来的模型很可能只是记住了那几条异常样本。6.3 “相关”不等于“因果”看到两个变量相关系数高达0.8很容易激动地觉得发现了重要规律。但数据挖掘项目里相关性只是给你一个“线索”不是“结论”。举个最简单的例子冰淇淋销量和溺水人数在夏天高度正相关但冰淇淋并不会让人溺水背后共同的原因是“天气热”。做特征工程时你可以把高相关变量作为候选特征但必须结合业务逻辑去判断否则很容易选出一些貌似相关、实则没有预测稳定性的特征。6.4 偏度和峰度结果异常时先回头查数据我见过不少同学算完偏度发现是5.3第一反应是“我的数据右偏很严重要取对数”。但更可能的情况是数据里混进了几条录入错误的值。比如年龄字段里出现一个180收入字段里出现一个负数。这些脏点对偏度和峰度的影响极其剧烈。所以我的排查顺序是先画箱线图再用IQR识别异常值最后才看偏度峰度。这一步看起来多余实际上能帮你省掉无数走了弯路之后的重新清洗时间。最后说点个人体会描述统计的“下半场”是我在每次建模前都会完整过一遍的固定动作。它不是理论课本上用来应付考试的知识点而是和异常值、分布形态、特征冗余这些实际问题直接挂钩的工具。我自己踩过的最大的坑是早期过于依赖均值加标准差导致异常值和偏态分布把特征工程带偏模型上线后效果忽高忽低。后来改成“分位数稳健统计量相关矩阵”三件套齐上阵再配合可视化一起看分析质量明显上了个台阶。如果你正在啃数据挖掘的数学基础建议不要只满足于会调describe()函数。试着把每个指标在什么场景下可靠、什么场景下失真想明白然后用项目数据亲自动手算一遍。遇到和常识不符的结果不要跳过那往往是你对数据理解加深的最好时机。

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价 →
↑