我正在处理从传感器接收到的燃油消耗数据,但有时数据包含噪声(突然跳跃或下降),导致数据不一致。我的目标是识别并消除这些异常值,以确保数据准确可靠,以供进一步分析。
以下是关键细节:
下面是我迄今为止实现的代码:
// value == Fuel Consumption
var data = FileReader.ReadCsv(path).Where(d => d.Value > 0).ToList();
var cleanedData = RemoveOutliers(data.Select(d => new DataPoint(d.Timestamp, d.Value, d.Speed)).ToList(), 1.5);
cleanedData = ApplyMovingAverage(cleanedData, 8);
List<AnomalyDetectionResult> anomalyDetectionResults = [];
foreach (var dataPoint in cleanedData)
{
// todo
}
static List<DataPoint> RemoveOutliers(List<DataPoint> data, double iqrFactor)
{
var values = data.Select(d => d.Value).ToList();
values.Sort();
double q1 = GetPercentile(values, 25);
double q3 = GetPercentile(values, 75);
double iqr = q3 - q1;
double lowerBound = q1 - iqrFactor * iqr;
double upperBound = q3 + iqrFactor * iqr;
return data.Where(d => d.Value >= lowerBound && d.Value <= upperBound).ToList();
}
static List<DataPoint> ApplyMovingAverage(List<DataPoint> data, int windowSize)
{
var smoothedData = new List<DataPoint>();
for (int i = 0; i < data.Count; i++)
{
var window = data.Skip(Math.Max(0, i - windowSize + 1)).Take(windowSize).ToList();
double avg = window.Average(d => d.Value);
smoothedData.Add(new DataPoint(data[i].Timestamp, avg, data[i].Speed));
}
return smoothedData;
}
static double GetPercentile(List<double> sortedValues, double percentile)
{
if (!sortedValues.Any()) return 0;
double rank = percentile / 100.0 * (sortedValues.Count - 1);
int lowerIndex = (int)Math.Floor(rank);
int upperIndex = (int)Math.Ceiling(rank);
if (lowerIndex == upperIndex) return sortedValues[lowerIndex];
return sortedValues[lowerIndex] + (rank - lowerIndex) * (sortedValues[upperIndex] - sortedValues[lowerIndex]);
}
public class DataPoint(DateTime timestamp, double value, int speed)
{
public DateTime Timestamp { get; set; } = timestamp;
public double Value { get; set; } = value;
public int Speed { get; set; } = speed;
}
在我的代码之前
我将不胜感激任何指导、建议或解决此问题的替代方法。
RemoveOutliers
对我来说似乎不正确。如果我理解正确的话,它将删除恒定斜坡的顶部和底部部分。所以我会完全删除这部分。
您可能会考虑切换到高斯滤波器,这些往往会比简单的移动平均线产生更好的结果。您还可以考虑进行一些频率分析,以针对您的特定情况优化滤波器参数。
更现代的方法可能是训练神经网络,假设您可以以某种方式获得大量真实数据和噪声数据进行训练。
您可能还想调查噪音的来源,如果您可以建立一个更好的模型来说明噪音是如何发生的,并且您是否可以找到一些更好的方法来解决问题。如果这是一辆车辆,也许与燃油晃动有关?如果是这样,您也许能够识别这些事件的开始和结束并忽略这些样本。