如何检测双打数组中的异常值?

时间:2018-05-26 13:40:51

标签: c# math

我正在尝试确定双打列表中是否存在数据异常值。基本上,如果任何东西低于10%的限制或高于90%。我有以下代码工作,但它与负数无法正常工作,我没有看到有什么问题。有没有更好的方法来接近那里,或者代码或数学中是否有明显的东西?

public bool DataHasOutliers(IEnumerable<double> results, Limits limits)
{
    foreach (double result in results)
    {
        //detect if any result values are in the low or high regions of the acceptable limits
        double deltaAbsolute = (limits.High - limits.Low) < 0 ? (limits.High - limits.Low) * -1 : limits.High - limits.Low;
        double absoluteResult = result < 0 ? result * -1 : result;
        double lowLimitAbsolute = limits.Low < 0 ? limits.Low * -1 : limits.Low;
        double upperThreshold = 0.9 * deltaAbsolute + limits.Low;
        double lowerThreshold = 0.1 * deltaAbsolute + limits.Low;
        if (absoluteResult >= upperThreshold)
        {
            "".Dump("Upper threshold violated");
            return true;
        }
        if (absoluteResult <= lowerThreshold)
        {
            "".Dump("Lower threshold violated");
            return true;
        }
    }
    return false;
}

public class Limits
{
    public double High { get; set; }
    public double Low { get; set; }
    public string Error { get; set; }
}

2 个答案:

答案 0 :(得分:2)

如果限制为[-10, 0]且结果为-5,则使用当前代码,您有效地检查5是否在[11, 19]中,这是不正确。

我建议保持边界的符号增加/减少它们的范围的1/10,然后在这个减小的范围内检查原始结果值:

double deltaAbsolute = Math.Abs(limits.High - limits.Low);
double lowerThreshold = limits.Low + 0.1 * deltaAbsolute;
double upperThreshold = limits.High - 0.1 * deltaAbsolute;
if (result >= upperThreshold)
{
    "".Dump("Upper threshold violated");
    return true;
}
if (result <= lowerThreshold)
{
    "".Dump("Lower threshold violated");
    return true;
}

答案 1 :(得分:0)

为什么要在循环中重新计算限制。
如果高>那么你不需要任何绝对的东西。

public bool DataHasOutliers(IEnumerable<double> results, Limits limits)
{
    if(limits.High < limits.Low) 
    {
         throw new ArgumentOutOfRangeException();
    }
    double delta = limits.High - limits.Low;
    double upperThreshold = 0.9 * delta + limits.Low;
    double lowerThreshold = 0.1 * delta + limits.Low;
    foreach (double result in results)
    {
        //detect if any result values are in the low or high regions of the acceptable limits
        if (result >= upperThreshold)
        {
            "".Dump("Upper threshold violated");
            return true;
        }
        if (result <= lowerThreshold)
        {
            "".Dump("Lower threshold violated");
            return true;
        }
    }
    return false;
}