在数值数据集中寻找"异常值"

3
我想比较(按增长率排序)高增长率和起始值非常低的劣势。
例如:
1. 开始:1,000,000 结束:1,100,000 增长:+10%
2. 开始:100,000 结束:120,000 增长:+20%
3. 开始:1 结束:10 增长:+900%
4. 开始:10 结束:15 增长:+50%
仅按增长率降序排序将得到:900%(3.),50%(4.),20%(2.),10%(1.)
但我希望得到的是:20%(2.),10%(1.),900%(3.),50%(4.),因为在我的情况下,很有可能3.和4.是统计上的异常值。
解决此问题的最佳方法是什么?我需要为起始值定义一个阈值吗?
谢谢!

1
有趣的问题。你能解释一下为什么你认为3和4是异常值而1和2不是吗?你对这些系统生长模型的基本假设是什么? - templatetypedef
在我们评估最佳方法之前,您必须提供有关概念模型的更多详细信息。一般来说,如果您拥有足够的数据(越多越好),您可以让分类器为您完成此操作。如果您想要手动基于规则的分类,则必须自己制定规则。 - Reut Sharabani
这些值是Twitter的关注者数量,我想确定哪个用户增长最显著。假设是新用户更容易实现高增长率。 - root66
2个回答

3
根据您提供的描述,问题可以分为两个部分:
  1. 从数据集中找到并排除“统计离群值”
  2. 将结果值按降序(或任何顺序)排序
第一个问题的通用解决方案和使用Microsoft Excel的示例在“Microsoft Excel工作表中的统计离群值检测”(http://www.codeproject.com/Tips/214330/Statistical-Outliers-detection)中描述。以下是一些理论和与您的情况相关的示例。

在数据集中寻找“异常值”可以通过计算每个数字的偏差来完成,以“Z分数”或“修改后的Z分数”表示,并将其与某些预定义的阈值进行测试。Z分数通常是相对于统计平均值的标准偏差数量(换句话说,它以“西格玛”为单位)。修改后的Z分数应用中位数计算技术来测量偏差,在许多情况下提供更强大的统计检测异常值。根据 IglewiczHoaglin 的建议(请参见引用文章),修改后的Z分数可以用数学方式写成:

Mi = 0.6745 * (Xi - Median(Xi)) / MAD,

MAD 代表中位数绝对偏差。数据集中任何一个数的修改后 Z 分数的绝对值超过 3.5 就被视为“离群值”。可以使用修改后的 Z 分数在 Microsoft Excel 工作表中检测与您情况相关的离群值,如下所述。

步骤 1. 打开 Microsoft Excel 工作表,在单元格 A1、A2、A3 和 A4 中输入值:900%、50%、20% 和 10%,分别对应。

步骤 2. 在 C1 中输入公式:=MEDIAN(A1:A4)。该单元格中的值对应于在步骤 1 中输入的数据集上计算出的中位数。

步骤 3. 在 C2 中输入数组公式:{=MEDIAN(ABS(MEDIAN(A1:A4)-A1:A4))}。作为提醒,为了输入数组公式,请选择单元格,在 Excel 公式栏中输入公式,然后单击组合键:CTRL-SHIFT-ENTER(注意大括号围绕表达式,这表示数组公式)。该单元格(C2)中的值对应于 MAD。

步骤4. 输入公式:=IF((0.6745*ABS(C$1-A1)>3.5*C$2), "异常值", "正常")在B列的第一行,并向下扩展到第4行。"异常值检测"的最终结果应出现在B列中。
A       B           C
900%    OUTLIER     35%
50%     NORMAL      0.35
20%     NORMAL  
10%     NORMAL  

因此,值为900%被视为“异常值”,而其他值则正常。对结果集进行排序将是一个简单的任务。
为了更清晰地解释,附带了Excel工作表示例。该算法可以在任何编程语言中实现(VBA、C#、Java等)。希望这能有所帮助。

乍一看似乎不错,但50%也可能是一个“异常值”,因为我的假设是,对于起始值较小的数据输入来说,在开始阶段实现更高的增长率更容易。这些值是Twitter的追随者。谢谢! - root66
1
@root66:我提供的查找统计“异常值”的解决方案基于NIST(美国)的建议(请参阅参考文章),因此在科学和工程社区中被广泛接受。您可以根据特定的用例设置“异常值”标准。如果您对答案满意,请将其标记为已接受。谢谢和问候, - Alexander Bell
1
@AlexBell 为什么你的解决方案中没有使用0.6745这个值,就像实际公式中一样:Mi=0.6745 * (Xi -Median(Xi)) / MAD? - Nawaf Alsulami
是的,应该是这样的。感谢您的留言。祝好。 - Alexander Bell

3

我的解决方案

private static List<double> StatisticalOutLierAnalysis(List<double> allNumbers)
{
    List<double> normalNumbers = new List<double>();
    List<double> outLierNumbers = new List<double>(); 
    double avg = allNumbers.Average();
    double standardDeviation = Math.Sqrt(allNumbers.Average(v => Math.Pow(v - avg, 2)));
    foreach (double number in allNumbers)
    {
        if ((Math.Abs(number - avg)) > (2 * standardDeviation))
            outLierNumbers.Add(number);
        else
            normalNumbers.Add(number);
    }

    return normalNumbers;
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接