我假定數字在一系列數字的異常查找
var nums = new List<double> {1,2,2.4,2.6,1.5,3,1.9};
列表中的項目清單分發正常;在這樣的系列中,我想過濾掉異常(它可以是1
和3
,因爲它們似乎是最偏離的值)。我必須使用動態系列,其值可能會發生變化,因此無法在條件檢查中硬編碼任何值。
我假定數字在一系列數字的異常查找
var nums = new List<double> {1,2,2.4,2.6,1.5,3,1.9};
列表中的項目清單分發正常;在這樣的系列中,我想過濾掉異常(它可以是1
和3
,因爲它們似乎是最偏離的值)。我必須使用動態系列,其值可能會發生變化,因此無法在條件檢查中硬編碼任何值。
如果假定的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)));
好吧,現在我明白OP的含義了...... – Nebr
@Nebr:對於一些問題,水晶球是不可或缺的...我必須承認我有一個不公平的優勢:我目前的項目是在一個電信數據庫中檢測異常。 –
對您的要求的一個非常普遍的答案:您需要定義什麼是異常。這是你的謂詞。然後相對於謂詞過濾列表。
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;
}
這應該在沒有指定過濾器值的情況下完成。 – user6634447
它可以。只需填寫你需要的東西即可。而不是d <3,寫出你需要的任何東西,這只是一個例子。如果過濾器的值是可變的,寫入d <_currentFilterValue或其他。 – Nebr
在我的情況下,會有值的範圍,我們不知道哪個是閾值,它是完全動態的。 – user6634447
任何你至今嘗試過? – fubo
定義「異常」 – Alex
爲什麼1.5也不是一個異常?我認爲1.5和1.9是奇數,因爲其餘的將按照沒有它們的順序排序。你怎麼知道**什麼是異常,什麼是好的? – quetzalcoatl