我有几个需要绘制的数据点系列。对于每个图形,可能由于错误而需要抛出一些点。一个例子如下:
圈出的区域是数据中的错误。
我需要的是一种过滤此数据的算法,以便通过用平线替换坏点来消除错误,如下所示:
是否有任何算法特别擅长检测错误点?你有什么提示可以指出我正确的方向吗?
编辑:错误点是任何与双方数据不一致的点。只要跳转后的数据看起来仍然一致,就可以有大跳跃。如果它位于图形的边缘,则大跳跃应该被视为错误。
答案 0 :(得分:2)
这是一个难以解决的问题;您的最终解决方案将最终依赖于流程,并且对您的情况而言是独一无二的。
话虽如此,您需要先了解您的数据:从一个样本到下一个样本,可能会出现什么样的变化?使用它,您可以使用以前的数据样本(可能是未来的数据样本)来确定当前样本是否是假的。然后,您将得到一个类似于:
的过滤器 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值。您可以独立地将上述逻辑应用于每个维度,如果只有一个维度是给您不好的数字,那么这将是合适的。例如,在一个维度是时间戳的情况下,这可能会特别成功,并且时间戳偶尔会出现伪造。
答案 1 :(得分:0)
如果无法通过眼睛去除异常值,请尝试使用http://www.ipf.tuwien.ac.at/cb/publications/pipeline.pdf中的kriging(带有错误术语)。这似乎很好地自动处理偶尔的极端噪音。我知道法国气象学家使用这种方法去除数据中的异常值(例如温度传感器旁边的火灾或者例如踢风传感器的东西)。
请注意,这一般是一个难题。有关错误的任何信息都很珍贵。有人踢了测量设备吗?然后,除了手动删除有问题的数据之外,你无能为力。你的噪音是否系统化?你可以通过做出(合理的)假设来做很多事情。