☰
Excel TRIMMEAN函数实战:剔除极端值,计算稳健平均值
2026/10/2 15:04:26 网站建设 项目流程

又到了每个月算绩效的时候。你面前这张评分表,二十个评委打分,平均值算出来3.8分,看起来还行,突然有个评委给了一两个极端低分,平均分立刻被拽下来,整个部门的绩效排序跟着乱套。这种被极端数字绑架的场景,Excel里其实有一个专门应对的函数:TRIMMEAN。TRIMMEAN的核心逻辑就是去除极端值后再做平均——先把数据按大小排序,按照你指定的比例从头部和尾部对称剪掉一定数量的数据点,再对剩余数据求平均值,比手工删掉最高最低分再计算要严谨得多。这篇文章我打算把TRIMMEAN的语法规则、不同平均算法的选型逻辑、实际案例和常见翻车点一次讲透,适合正在做绩效考核、销售分析、竞赛评分、实验数据处理的Excel用户参考。

1. TRIMMEAN删数据的数学规则:percent参数与截断数量

1.1 percent参数:你到底想让Excel丢掉几个数

第一次用TRIMMEAN的人,十有八九会被第二个参数绕晕。先看语法:

TRIMMEAN(array, percent)
  • array:要计算平均值的数据区域,比如A1:A20。
  • percent:要从数据集中剔除的数据点比例,取值在0到1之间。注意,这里的核心词是“比例”,不是“个数”。

一个很常见的错误是:我想去掉一个最高分和一个最低分,所以写TRIMMEAN(B2:G2, 2)。这个写法一定会让你收到一个#NUM!错误,因为percent=2已经超出了Excel允许的合理区间。正确理解是这样:percent=0.2表示整个数据集里20%的数据会被排除,这20%不是只砍一边,而是对称分配——最小的10%砍掉,最大的10%也砍掉,两头各10%。所以对10个数来说,TRIMMEAN(A1:A10,0.2)的真正效果是:先排序,把最小的1个数和最大的1个数丢出去,中间8个数求平均。

再换个角度:TRIMMEAN和“手动删除最高最低后计算平均”不是一回事。手动删除是固定个数,而TRIMMEAN是固定比例。如果你面对的是20个数据,设置0.2,那么整体会排除20×0.2=4个数,即头尾各2个,剩下16个参与平均。数据量越大,同样比例下被排除的个数越多。

1.2 向下取偶的截断逻辑,为什么不是四舍五入

很多人会问:设了比例之后,Excel到底是怎么决定剪掉几个数的?我查过微软官方文档,内部规则可以概括成三步:

  1. 计算数据总数 × percent,得到一个候选数。
  2. 把这个候选数向下取整到最近的偶数。
  3. 用这个偶数除以2,得到“头部剔除数量”和“尾部剔除数量”。

举个例子,数据总数是15,percent=0.2,那么15×0.2=3。为什么最后不是剪掉3个,而是剪掉2个?因为3向下取偶是2,于是头尾各剪1个,总共剪2个。这看起来有点“奇怪”,但逻辑上很好理解:要保证头尾对称,每次剔除必须成对进行。如果剪掉3个,就无法做到头尾各占1.5个。

这个细节让很多人在验证公式时产生困惑。比如你手算“15个数据剪掉20%”,预期是3个,结果发现TRIMMEAN只剪了2个,于是怀疑函数算错了。其实没算错,是“就近取偶”规则在起作用。可以把它想象成Excel为了保持剪刀平衡,只能成双地剪,奇数个的修剪请求会被自动降级到最近的偶数。

1.3 一份常用比例速查表,直接对着用就行

下面的表总结了不同数据量和不同percent下,真正被排除的数据点个数:

数据总数percent设置总数×percent向下取偶结果头尾各去剩余参与平均的个数
100.110010
100.22218
150.232113
200.244216
200.366314
300.132128
300.266324

注意第一行,数据总数10、percent=0.1时,10×0.1=1,向下取偶得到0,所以一个数据都不会剪。如果你拿到一组8条记录,设置percent=0.1,同样因为8×0.1=0.8,向下取偶还是0,函数等于什么都没干。这类“设置了比例但没有效果”的情况,在第4章会专门展开讲。

理解了上述规则之后,TRIMMEAN的行为就完全可以预测了,后续排错也就有了抓手。

2. 三种均值怎么选:TRIMMEAN、AVERAGE、MEDIAN的实战对比

2.1 同一组数据,三种平均算出来差多少

我经常在培训里用一组数据说明三个函数的差别。假设你收到这样10个数:

1, 2, 30, 31, 32, 33, 34, 35, 36, 100

分别计算三种结果:

计算方式结果解读
AVERAGE33.4被100明显拉高,也受到左侧1、2的拖累
MEDIAN32.5只看中间位置,稳健但完全忽略两头数据
TRIMMEAN(区域,0.2)29去掉排序后最小的1和最大的100,剩下8个求平均

TRIMMEAN在这里得到一个更贴近“大众水平”的29。它没有像MEDIAN那样只取一个位置,而是保留了中间80%数据的全部信息,同时把两端最极端的10%各甩掉。

再举个评分的直觉例子。6个评委给分如下:

2, 6, 7, 8, 9, 10
  • AVERAGE= 7,被那个2分拉得明显偏低。
  • TRIMMEAN(区域,0.2):6×0.2=1.2,向下取偶后是0?等等,这里不能直接取0。重新算:6×0.2=1.2,向下取偶到0,一个都不剪。哦,这个例子不对,换TRIMMEAN(区域,0.3333)?不行。用评委例子时,如果6个评委要去掉最高最低各一个,应该用TRIMMEAN(区域,2/6),6×(2/6)=2,向下取偶2,头尾各去1,剩下6、7、8、9,平均=7.5。这比直接平均的7更合理,也更接近“去掉一个最高分、去掉一个最低分”的竞赛规则。

所以实际工作中,TRIMMEAN的价值在于:它不会像AVERAGE那样被个别妖孽数据牵着走,也不会像MEDIAN那样完全放弃数据的数值大小信息,而是通过按比例修剪,得到一个更稳、但又保留了大部分真实数据信息的中心趋势值。

2.2 我的选型判断标准

什么样的场景适合TRIMMEAN?我一般用下面这个判断清单:

  • 数据里存在明显离群点,你又不想主观决定“到底删哪个数”。
  • 数据量较大,且极端值属于“噪音”而非研究对象。比如评委打分、销售流水、设备测量值、用户体验评分。
  • 希望通过固定比例统一处理一批数据,让规则透明可复现——这正是绩效考核最看重的一点。
  • 数据结构比较干净,没有大量文本、空值和错误值混入。

反过来,这几种情况别用:

  • 数据量太小。总共3到5个数据,再剪掉一两个,剩余样本信息太少,结果可能还不如直接用中位数。
  • 极端值本身就是业务关注对象。比如做风险分析时,最大损失金额恰恰是最重要的指标,剪掉它就等于把核心信息弄丢了。
  • 合同、制度、审计要求明确规定了算法,不能用替代性算法。
  • 你需要保证所有数据点都被纳入统计口径,哪怕它是异常的。

2.3 判断数据是否被极端值绑架的快速检查法

动手写TRIMMEAN之前,可以先花三秒钟做个预检,判断这组数据是不是真的需要修剪。我常用的办法是看平均值和中位数的差值:

=ABS(AVERAGE(D2:D31) - MEDIAN(D2:D31))

如果这个差值相对数据本身的量级很大,比如平均值30,中位数15,差了整整一倍,那说明极端值影响相当严重。此时用TRIMMEAN就非常合适。如果两者本来就接近,说明数据分布比较正常,用普通AVERAGE也没什么问题。

也可以用条件格式快速可视化:选中数据区域,添加“数据条”或“箱线图”类型的图表,一眼就能看出有没有明显脱离群体的点。判断做完,再决定修剪比例,比直接套一个0.1或0.2要靠谱得多。

3. 分数去极值与销售清洗:两个可直接抄走的实例

3.1 六位评委打分的去高去低平均分

场景:你有一张员工评分表,B列到G列是6位评委的打分,H列要算“去掉一个最高分、去掉一个最低分后的平均分”。

第一版公式可以这样写:

=TRIMMEAN(B2:G2, 2/COUNT(B2:G2))

这里2/COUNT(B2:G2)的意思很明确:要剔除2个数,占总数的比例就是2除以评委人数。对于6位评委,percent=2/6≈0.3333,数据总数×percent=6×0.3333≈2,向下取偶仍是2,于是头尾各剪1个,剩下的4个数求平均。关键在于COUNT是动态计算的,如果某位员工只有5位评委打分,公式会自动变成2/5,不需要手动改。

但这里有一个天然的边界问题:如果评委人数只有1个或2个,2/COUNT会大于等于1,TRIMMEAN会直接返回#NUM!。所以实际落地时,我给业务部门的模板公式通常会加一层防护:

=IF(COUNT(B2:G2)>=3, TRIMMEAN(B2:G2, 2/COUNT(B2:G2)), AVERAGE(B2:G2))

当评委不足3人时,一律用普通平均;3人及以上才启用修剪逻辑。这在实际考核场景里很关键——你不希望一个五六个评委的季度考核,因为某个员工请假导致只有2个评委打分,整列公式报错,最后交上去一张红红绿绿的表。

如果你特别排斥这种动态百分比写法,也可以用更传统的数组公式,思路是直接取中间段数据求平均:

=AVERAGE(SMALL(B2:G2, ROW(INDIRECT("2:"&COUNT(B2:G2)-1))))

老版本Excel需要按Ctrl+Shift+Enter确认输入。这个公式能精确做到“去掉最小一个、去掉最大一个”,不依赖比例换算。但它的缺点是计算逻辑不直观,看公式的人不容易理解。所以我个人还是更推荐TRIMMEAN加COUNT的方案,业务部门拿到公式自己也能看懂:去掉2个数,所以比例是2除以人数。

3.2 销售明细表里按店剔除异常订单

另一个高频场景是销售数据清洗。假设你有一家门店30天的日销售额,在B2:B31区域,想剔除最大一笔和最小一笔之后看日均。公式照样是:

=TRIMMEAN(B2:B31, 2/COUNT(B2:B31))

30天乘2/30等于2,取偶后还是2,头尾各去1笔。这样得到的日均销售比直接AVERAGE更抗干扰。某天大客户突然来了一笔50万的大单,如果把这一天保留在均值里,整月分析都会失真;直接删掉这一天,又有点“人为干预”的嫌疑。用TRIMMEAN给出一个透明规则,所有人都知道是“按比例自动剔除”,讨论成本低很多。

这里分享一个容易踩的坑:分母千万别用COUNTA。COUNTA会统计非空单元格,一旦销售明细列里有导入进来的文本说明、备注信息,COUNTA会把它们也数进去,导致percent偏大,修剪量超出预期。而COUNT只数数值,和TRIMMEAN的忽略文本规则能对齐。

如果数据里存在空行,也要小心区域引用范围。比如B2:B200选了很大一片区域,中间某些天没数据,TRIMMEAN在计算时会忽略空单元格,但COUNT(B2:B200)也只数有数值的单元格,所以百分比计算依然能对齐,这算是TRIMMEAN比较智能的地方。不过最好还是把区域范围收窄到实际数据区域,避免后续添加备注列时干扰公式。

3.3 按组剔除极值的进阶写法

销售分析常常不只看整个表,可能要看每个业务员、每个门店自己的均值。这时候就有人问:TRIMMEAN有没有像AVERAGEIF那样的条件版本?很遗憾,TRIMMEAN没有条件版函数。但如果你用的是Excel 365,可以利用FILTER函数先取出某个业务员的数据,再丢给TRIMMEAN:

=TRIMMEAN(FILTER(C$2:C$1000, A$2:A$1000=E2), 2/COUNT(FILTER(C$2:C$1000, A$2:A$1000=E2)))

这个公式的意思是:从C列里筛出业务员等于E2的所有销售额,然后按2除以对应数量的比例做修剪均值。E2是某个业务员的名字,下拉填充就能算完所有人。

老版本Excel没有FILTER,我用过两种替代方案:一是加辅助列,先用IF生成一组只保留目标业务员数值的辅助列,再对辅助列套TRIMMEAN;二是使用数组公式配合INDEX和SMALL。辅助列虽然多占一列,但对业务同事最友好,因为他们能直观看到哪些数被剔除了。自动化程度要求高时,再推荐直接交给Python处理,这个在文章第5章展开。

4. 容易翻车的边界情况:percent、脏数据与隐藏行

4.1 percent参数的四个常见报错原因

TRIMMEAN的报错不算多,但每种报错都对应着一个真实使用场景。我梳理一份常见报错对照表:

错误值常见原因修复思路
#NUM!percent小于0或大于等于1检查percent参数,尤其要确认没有把“2”直接写成第二个参数
#DIV/0!区域内没有数值,全是文本或空单元格先清洗数据,用COUNT检查数值数量
#N/A区域里有错误值被函数捕捉修复来源,或先将错误值替换为空白再处理
#VALUE!直接使用包含文本的常量数组,例如TRIMMEAN({1,2,"a"},0.2)尽量使用单元格区域引用,而不是手写数组常量

这里我要单独强调一下percent>=1的坑。某个同事的做法是把百分比直接输入成20,因为单元格恰好是百分比格式,他以为20就是20%。但Excel内部实际存储的是20,不是0.2,TRIMMEAN直接返回#NUM!。正确的做法是输入0.2,或者输入20%并让Excel在内部自动保存为0.2。判断方法很简单:点一下该单元格,看编辑栏里显示的是0.2还是20,后者就要重新输入。

4.2 数据量太小导致“白剪”

有朋友问我:我明明设置了10%的修剪比例,为什么结果跟平均分完全一样?很可能是数据的数量级太小了。比如8个数据,8×0.1=0.8,向下取偶后是0,等于一个没剪。

这不是函数bug,而是前面说的“向下取偶”规则造成的必然结果。知道了这个规则,就能提前预判:想剪头尾各一个数,至少要让数据总数×percent落在2到4这个区间。最简单的解法是改用动态比例,比如明确要剪2个数,就用2/COUNT(区域),而不是纠结写0.1还是0.2。

话说回来,如果数据总数只有6个、8个,与其不停调percent,不如直接考虑用中位数或固定掐头去尾的SMALL组合公式,至少在业务沟通上更直接。

4.3 文本、错误值与隐藏行:脏数据入场前的预检

TRIMMEAN在区域引用情况下,会遵循Excel统计函数的一般规则:忽略文本、逻辑值和空单元格。这不是什么问题。真正的问题是错误值,比如#N/A或#DIV/0!,它们不会像文本那样被忽略,而是会直接传染给TRIMMEAN的最终结果。一个区域里只要有一个#N/A,整个结果就不可能算出来。

另外很多人忽略的一点:TRIMMEAN不会忽略隐藏行。它和SUBTOTAL完全不同。我有一次做报表,为了比对效果,手工隐藏了几行评分最低的记录,然后发现TRIMMEAN的结果纹丝不动,还以为表格没刷新。实际情况是,隐藏行照样参与修剪和平均计算。如果你确实只想对可见行进行计算,就得先把数据筛选好再复制到新区域,或者改用SUBTOTAL配合辅助列实现。

再提一句文本型数字。从系统导出的Excel,经常出现那种左上角带绿色三角的文本型数字。它们看起来是数字,但TRIMMEAN在忽略文本的规则下,会把它们当空气,导致数值数量比肉眼看到的少。解决方法也简单:选中整列,用“分列”功能直接点完成,或者用选择性粘贴乘1,把文本型数字强制转成数值。这也是我接手业务报表时第一个检查的动作。

4.4 我的#DIV/0!排错记录

去年帮运营部门处理过一张门店销售评分表,打开之后满屏#DIV/0!,一片红。第一反应以为是percent参数有问题,点进去看公式,0.2写得好好的,奇怪。

我用三个步骤定位:

  1. 先用COUNT检查区域内的数值数量,结果显示0。
  2. 再用COUNTA检查非空单元格数量,结果显示有78。
  3. 马上意识到:这78个单元格全是文本型数字或者字符串,根本没有真正的数值。

最后发现,这批数据是从某个内部系统导出后,又经过了文本拼接处理,所有数字都变成了文本。修复过程并不复杂:对销售列执行“分列”,用固定宽度或分隔符方式直接完成转换,再刷新公式,结果全部正常。这次排错让我养成了一个习惯:任何统计类函数返回异常时,永远先怀疑数据源,而不是先怀疑函数本身。如果你也遇到类似问题,可以先在某空白单元格输入=COUNT(区域),看看返回的是不是预期的数值个数,就能快速判断数据里有没有隐藏的文本暗雷。

5. 跳出Excel看截尾均值:Python复现与Power Query辅助方案

5.1 截尾均值在统计学里的定位

TRIMMEAN在统计学里有个正式名字:截尾均值,或者叫修剪均值。它属于稳健统计里的一类位置估计量。稳健的意思是:当我们的数据中存在少量离群点时,统计结果不会被这些点带偏得太严重。普通均值虽然效率高,但对极端值极其敏感;中位数虽然稳健,却会放弃很多数值信息。截尾均值正好站在两者中间,通过“按比例去掉两端”实现一种温和的稳健性。

理解了这层背景,你就会明白为什么TRIMMEAN的参数设计成“比例”而不是“个数”。比例的形式天然允许它适配不同数据量,从20条到2万条都能用同一个规则,这在大规模数据自动处理里非常关键。

5.2 Python一行代码复现TRIMMEAN逻辑

在Python里复现TRIMMEAN很简单,用scipy.stats.trim_mean。但这里有一个相当于“魔鬼细节”的差异,我必须单独拎出来讲:

  • Excel的TRIMMEAN(数据, 0.2)表示整体剔除20%,也就是头尾各10%。
  • Python的scipy.stats.trim_mean(数据, proportiontocut=0.2)表示每一边各剔除20%,整体剔除40%。

如果你把Excel里的0.2原封不动搬到Python,算出来的结果会跟你预想的完全不一样。正确的对应写法是:

from scipy.stats import trim_mean data = [1, 2, 30, 31, 32, 33, 34, 35, 36, 100] result = trim_mean(data, proportiontocut=0.1) # 相当于是Excel的0.2 print(result) # 29.0

这个例子和第2章那个表对应上了,python结果同样等于29。所以跨工具核对时,先确认“你的0.2到底是指单边还是双边比例”,这是很多人踩过的最痛的坑。

5.3 批量Excel自动化:pandas加trim_mean的清洗模板

日常处理几十行,用Excel公式完全够了。但当你要对几十个Excel文件、上万行数据做统一修剪均值时,逐行下拉公式反而低效。这时候我习惯直接用Python写个小脚本,一次性把数据读进来、算好、写回去,既省时间又不容易漏。

下面是一个可以直接修改使用的模板。假设你手头有一张Excel表格,里面有多位员工的评分数据,列结构是姓名加多个评分列,你要在最后新增一列“修剪均值”,统一按20%整体比例做截尾:

import pandas as pd from scipy.stats import trim_mean df = pd.read_excel("评分表.xlsx", sheet_name="Sheet1") # 假设前1列是姓名,后面的都是评分列 score_cols = df.columns[1:] # 按行计算,基准比例按Excel的0.2换算成Python的0.1 df["修剪均值"] = df[score_cols].apply( lambda row: trim_mean(row.dropna().values, proportiontocut=0.1), axis=1 ) df.to_excel("评分表_输出.xlsx", index=False)

注意这里我用row.dropna()把空值先去掉,避免trim_mean因为空值返回NaN。另外,proportiontocut=0.1是Excel里0.2的对应值,如果你要改比例,记住“Excel percent除以2”就是Python单边比例。

写回Excel需要依赖openpyxl或xlsxwriter,安装时一步到位即可:

pip install pandas scipy openpyxl

如果你不想引入scipy,只想用pandas,思路也很直接:排序后手工掐头去尾再求平均。但既然scipy一行就能解决,没必要自己造轮子。

5.4 Power Query里的无内置替代方案

Power Query目前没有直接的TRIMMEAN函数。如果你正在搭建自动刷新报表,又不想返回Excel算,可以用一段简单的M语言自定义函数。逻辑就是:先排序,再按比例掐头去尾,最后取平均。整体代码如下:

(values as list, percent as number) => let sortedList = List.Sort(values), count = List.Count(sortedList), excludeCount = Number.IntegerFloor(count * percent / 2) * 2, keptList = List.Range(sortedList, excludeCount / 2 / 1 + 0, count - excludeCount), result = List.Average(keptList) in result

需要说明的是,这只是对齐Excel剔除逻辑的一种M语言近似实现,边界情况和浮点细节未必能完全一致。在Power Query里做快速探索性分析可以,真要交付正式报表,我更建议先把数据源清洗干净,再回到Excel或Python里用成熟函数计算。

在我看来,TRIMMEAN的价值不在于它多复杂,而在于它帮你把“剪掉极端值”这件事从拍脑袋变成了可解释、可复制的规则。最后再分享一个我个人的小习惯:每次用TRIMMEAN之前,先选中数据源区域按F9或直接看状态栏的平均值,再对比TRIMMEAN的结果,两张数字一对照,你对这批数据的分布就有数了。数据越脏、口径越不统一,这个习惯越能帮你提前躲开后面一整片麻烦。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询