如何检测ArrayList中的异常值

Ash*_*ton 4 java arraylist outliers

我正在尝试一些代码,这些代码允许我搜索我的ArrayList并检测"好值"的常见范围之外的任何值.

示例:100 105 102 13 104 22 101

我怎样才能编写代码来检测(在这种情况下)13和22不在100左右的"良好值"范围内?

skl*_*tch 7

package test;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

public class Main {
    public static void main(String[] args) {
        List<Double> data = new ArrayList<Double>();
        data.add((double) 20);
        data.add((double) 65);
        data.add((double) 72);
        data.add((double) 75);
        data.add((double) 77);
        data.add((double) 78);
        data.add((double) 80);
        data.add((double) 81);
        data.add((double) 82);
        data.add((double) 83);
        Collections.sort(data);
        System.out.println(getOutliers(data));
    }

    public static List<Double> getOutliers(List<Double> input) {
        List<Double> output = new ArrayList<Double>();
        List<Double> data1 = new ArrayList<Double>();
        List<Double> data2 = new ArrayList<Double>();
        if (input.size() % 2 == 0) {
            data1 = input.subList(0, input.size() / 2);
            data2 = input.subList(input.size() / 2, input.size());
        } else {
            data1 = input.subList(0, input.size() / 2);
            data2 = input.subList(input.size() / 2 + 1, input.size());
        }
        double q1 = getMedian(data1);
        double q3 = getMedian(data2);
        double iqr = q3 - q1;
        double lowerFence = q1 - 1.5 * iqr;
        double upperFence = q3 + 1.5 * iqr;
        for (int i = 0; i < input.size(); i++) {
            if (input.get(i) < lowerFence || input.get(i) > upperFence)
                output.add(input.get(i));
        }
        return output;
    }

    private static double getMedian(List<Double> data) {
        if (data.size() % 2 == 0)
            return (data.get(data.size() / 2) + data.get(data.size() / 2 - 1)) / 2;
        else
            return data.get(data.size() / 2);
    }
}
Run Code Online (Sandbox Code Playgroud)

输出:[20.0]

解释:

  • 从低到高对整数列表进行排序
  • 将整数列表分成两部分(按中间)并将它们放入 2 个新的单独的 ArrayList(称为“左”和“右”)
  • 在这两个新的 ArrayList 中找到中间的数字(中位数)
  • Q1 是左侧的中位数,Q3 是右侧的中位数
  • 应用数学公式:
  • IQR = Q3 - Q1
  • LowerFence = Q1 - 1.5*IQR
  • UpperFence = Q3 + 1.5*IQR
  • 有关此公式的更多信息:http://www.mathwords.com/o/outlier.htm
  • 循环遍历我的所有原始元素,如果其中任何元素低于下栅栏或高于上栅栏,则将它们添加到“输出”ArrayList
  • 这个新的“输出”ArrayList 包含异常值

  • @MladenAdamovic:一般来说,Stackoverflow 中的代码应该更多地被视为对其他人的指导,而不是“生产代码,准备好复制/粘贴”,至少专业工程师就是这么做的。根据边缘情况进行批评总是比像 sklimkovitch 那样编写完整的算法更容易。就像流行歌曲所说:“谦虚”;-) (7认同)

Jon*_*oni 6

检测异常值有几个标准.最简单的一个,如Chauvenet的标准,使用从样本计算的平均值和标准差来确定值的"正常"范围.超出此范围的任何值都被视为异常值.

其他标准是Grubb的测试Dixon的Q测试,如果样本来自偏斜分布,可能会比Chauvenet更好的结果.


Tra*_*vis 5

Grubb 测试的实现可以在MathUtil.java中找到。它将找到一个异常值,您可以将其从列表中删除并重复,直到删除所有异常值。

取决于commons-math,所以如果您使用 Gradle:

dependencies {
  compile 'org.apache.commons:commons-math:2.2'
}
Run Code Online (Sandbox Code Playgroud)


Jig*_*shi 1

  • 找到列表的平均值
  • 创建一个Map将数字映射到距平均值的距离
  • 按与平均值的距离对值进行排序
  • 并区分最后一个n数字,确保距离没有不公平