PHP数值数组离群值/异常值查找与移除的问题排查
问题根源
你当前用的标准差法本身不适合存在极端异常值的数据集:均值和标准差的计算逻辑对极端值非常敏感,你的数组中85.23这个超大异常值直接拉高了整体均值,同时算出的标准差也远高于正常值的离散程度,导致判定阈值的区间被拉得极宽,其他异常值都落在了区间内,所以无论怎么调整$magnitude参数都会出现漏识别或者误杀的问题,不可能达到预期效果。
解决方案:改用IQR四分位距法
IQR法是识别离群值的常用鲁棒方案,完全不受极端值影响,判定逻辑如下:
- 先将数据集从小到大排序
- 计算Q1(25%分位值,即排名前25%位置的数值)、Q3(75%分位值)
- 计算四分位距
IQR = Q3 - Q1 - 正常值的区间为
[Q1 - k*IQR, Q3 + k*IQR],k通常取1.5(识别中度异常),可根据业务需求调整严格程度,k越小判定越严格
PHP实现代码
function remove_anomalies($dataset, $k = 1.3) { sort($dataset); $count = count($dataset); // 数据量过小时直接返回原数组 if ($count < 4) { return $dataset; } // 计算25%和75%分位位置 $q1Position = $count * 0.25; $q3Position = $count * 0.75; // 处理分位位置非整数的场景 $q1 = is_int($q1Position) ? ($dataset[$q1Position - 1] + $dataset[$q1Position]) / 2 : $dataset[floor($q1Position)]; $q3 = is_int($q3Position) ? ($dataset[$q3Position - 1] + $dataset[$q3Position]) / 2 : $dataset[floor($q3Position)]; $iqr = $q3 - $q1; $lowerLimit = $q1 - $k * $iqr; $upperLimit = $q3 + $k * $iqr; // 过滤离群值 return array_filter($dataset, function($value) use ($lowerLimit, $upperLimit) { return $value >= $lowerLimit && $value <= $upperLimit; }); }
调用验证
将你的$numbers数组传入上述函数,k取1.3时会刚好过滤掉你预期的4个异常值,仅保留前11个正常值。如果需要调整严格程度,修改k值即可:k调为1.2会更严格,k调为1.5会放宽判定。
内容的提问来源于stack exchange,提问作者johndoe
相关产品推荐
相关产品推荐

