2016-10-20 20 views
-2

我假定數字在一系列數字的異常查找

var nums = new List<double> {1,2,2.4,2.6,1.5,3,1.9}; 

列表中的項目清單分發正常;在這樣的系列中,我想過濾掉異常(它可以是13,因爲它們似乎是最偏離的值)。我必須使用動態系列,其值可能會發生變化,因此無法在條件檢查中硬編碼任何值。

+2

任何你至今嘗試過? – fubo

+8

定義「異常」 – Alex

+1

爲什麼1.5也不是一個異常?我認爲1.5和1.9是奇數,因爲其餘的將按照沒有它們的順序排序。你怎麼知道**什麼是異常,什麼是好的? – quetzalcoatl

回答

0

如果假定的nums項分配要正常一個,我們可以把一個值爲異常,如果它超出了[mean - k * sigma..mean + k * sigma]範圍(sigma代表標準偏差),其中k通常2(95%),3(99.76%),有時甚至5。 如果這是你的情況下,可以實現

public static IEnumerable<T> Anomaly<T>(IEnumerable<T> source, 
             Func<T, double> map, 
             double maxSigma = 3.0) { 
    if (null == source) 
    throw new ArgumentNullException("source"); 
    else if (null == map) 
    throw new ArgumentNullException("map"); 

    T[] data = source.ToArray(); 

    if (data.Length <= 1) 
    yield break; 

    double s = 0.0; 
    double s2 = 0.0; 

    foreach (var item in data) { 
    double x = map(item); 

    s += x; 
    s2 += x * x; 
    } 

    double mean = s/data.Length; 
    double sigma = Math.Sqrt(s2/data.Length - (s/data.Length) * (s/data.Length)); 
    double leftMargin = mean - maxSigma * sigma; 
    double rightMargin = mean + maxSigma * sigma; 

    foreach (var item in data) { 
    double x = map(item); 

    if (x < leftMargin || x > rightMargin) 
     yield return item; 
    } 
} 

所以你可以找到不同的k異常:

var nums = new List<double> { 1, 2, 2.4, 2.6, 1.5, 3, 1.9 }; 

// k = 3 (typical criterium of 3 sigma deviation - 99.76%) - empty output 
Console.Write(string.Join(", ", Anomaly(nums, x => x, 3))); 

// k = 1 (unusual criterium of just 1 sigma deviation - 67%) the output is "1, 3" 
Console.Write(string.Join(", ", Anomaly(nums, x => x, 1))); 
+0

好吧,現在我明白OP的含義了...... – Nebr

+0

@Nebr:對於一些問題,水晶球是不可或缺的...我必須承認我有一個不公平的優勢:我目前的項目是在一個電信數據庫中檢測異常。 –

0

對您的要求的一個非常普遍的答案:您需要定義什麼是異常。這是你的謂詞。然後相對於謂詞過濾列表。

var nums = new List<double> {1,2,2.4,2.6,1.5,3,1.9}; 
Predicate<double> anomalyPredicate = IsNoAnomaly; // Definition of a predicate 
List<double> listWithoutAnomalies= nums.FindAll(anomalyPredicate); // Find every item that is not an anomaly 

我們假設異常是數字是3或更大。那麼你有:

private static bool IsNoAnomaly(double d) 
{ 
    return d < 3; 
} 

但當然,IsNoAnomaly可能是任何布爾函數返回。

編輯:又如:如果在可能未達到或超過運行時間_currentThreshold確定的閾值,則該函數將是:

private static bool IsNoAnomaly(double d) 
{ 
    return d < _currentThreshold; 
} 
+0

這應該在沒有指定過濾器值的情況下完成。 – user6634447

+0

它可以。只需填寫你需要的東西即可。而不是d <3,寫出你需要的任何東西,這只是一個例子。如果過濾器的值是可變的,寫入d <_currentFilterValue或其他。 – Nebr

+0

在我的情況下,會有值的範圍,我們不知道哪個是閾值,它是完全動態的。 – user6634447