我有几个系列的数据点需要绘制成图表。对于每个图形,由于错误,可能需要丢弃一些点。一个例子如下:
圈出的区域是数据中的错误。
我需要的是一种算法来过滤这些数据,以便通过用扁平线替换坏点来消除错误,如下所示:
有没有特别擅长检测错误点的算法?您有什么提示可以为我指明正确的方向吗?
编辑:错误点是任何看起来与两侧数据不一致的点。可以有大的跳跃,只要跳跃后的数据看起来还是一致的。如果它在图表的边缘,大的跳跃可能应该被认为是错误的。
最佳答案
这是一个很难通用解决的问题;您的最终解决方案最终将非常依赖于流程,并且对您的情况而言是独一无二的。
话虽这么说,但您需要先了解您的数据:从一个样本到下一个样本,什么样的变化是可能的?使用它,您可以使用以前的数据样本(可能还有 future 的数据样本)来确定当前样本是否是伪造的。然后,您将得到一个类似于以下内容的过滤器:
const int MaxQueueLength = 100; // adjust these two values as necessary
const double MaxProjectionError = 5;
List<double> FilterData(List<double> rawData)
{
List<double> toRet = new List<double>(rawData.Count);
Queue<double> history = new Queue<double>(MaxQueueLength); // adjust queue length as necessary
foreach (double raw_Sample in rawData)
{
while (history.Count > MaxQueueLength)
history.Dequeue();
double ProjectedSample = GuessNext(history, raw_Sample);
double CurrentSample = (Math.Abs(ProjectedSample - raw_Sample) > MaxProjectionError) ? ProjectedSample : raw_Sample;
toRet.Add(CurrentSample);
history.Enqueue(CurrentSample);
}
return toRet;
}
然后,神奇之处在于您的 GuessNext 函数。在这里,您将接触到特定于您的情况的内容,并且应该考虑您所知道的关于收集数据的过程的一切。输入变化的速度有物理限制吗?您的数据是否包含可以轻松过滤的已知错误值?
这是一个 GuessNext 函数的简单示例,它根据您的数据的一阶导数进行计算(即,当您只查看数据的一小部分时,它假设您的数据大致是一条直线)
double lastSample = double.NaN;
double GuessNext(Queue<double> history, double nextSample)
{
lastSample = double.IsNaN(lastSample) ? nextSample : lastSample;
//ignore the history for simple first derivative. Assume that input will always approximate a straight line
double toRet = (nextSample + (nextSample - lastSample));
lastSample = nextSample;
return toRet;
}
如果您的数据特别嘈杂,您可能需要在将其传递给 GuessNext 之前对其应用平滑过滤器。您只需花一些时间在算法上,就可以得出对您的数据有意义的东西。
您的示例数据似乎是参数化的,因为每个样本都定义了 X 和 Y 值。您可以将上述逻辑独立应用于每个维度,如果只有一个维度是给您错误数字的维度,那么这将是合适的。例如,在一个维度是时间戳并且时间戳偶尔是伪造的情况下,这可能特别成功。
关于algorithm - 我应该如何过滤这些数据?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/3738334/