如何在 C# 中使用 Deedle 过滤或删除基于前一个值的值?

How to filter or drop a value based on the previous one using Deedle in C#?

我正在处理来自传感器的数据。有时这些传感器会断电和断电,因此我可以在一个帧中有以下类型的时间序列,我们称之为 "myData":

[7.438984; 0,000002; 7.512345; 0.000000; 7.634912; 0.005123; 7.845627...]

因为我只需要3位小数的精度,所以我对帧中的数据进行了四舍五入:

var myRoundedData = myData.ColumnApply((Series<DateTime, double> numbers) => numbers.Select(kvp => Math.Round(kvp.Value, 3)));

我从框架中获取列并过滤零“0.000”:

var myFilteredTimeSeries = from kvp in myTimeSeries where kvp.Value != 0.000 select kvp;

所以,我的时间序列被部分过滤了: [7.439; 7.512; 7.635; 0.006; 7.846...]

但是,值“0.006”无效!

我如何根据先前的值实现优雅的过滤语法,例如变化率中的 "percent limit":

如果 (0.006 / 7.635) * 100 < 0.1 那么 ---> 删除/删除 (0.006)

如果您只想查看 previous/next 值,那么您可以将系列移动一个并将其压缩为原始值。这将为您提供一系列对(一个值连同 previous/next 值):

var r = actual.ZipInner(actual.Shift(1));

如果您想查看指定元素周围的更多元素,那么您将需要 Deedle 提供的窗口函数之一:

最简单的示例是使用 WindowInto 获取一个值及其前面的 4 个值:

var res = values.WindowInto(5, win => 
   // 'win' is a series with the values - do something clever here! 
);

其中一个关键是专注于涉及值及其 "neighbourhood" 的方法,就像 @tomaspetricek 之前指出的那样(谢谢!)。 我的目标是找到一个 "free-of-noise" 时间戳或键来构建一个框架并执行一个 AddColumn 操作,这本质上是一个 JoinKind.Left 操作。

为了解决这个问题,我使用 Pairwise() 方法来关注 "Item1"(当前值)和 "Item2"(下一个值),如下所示:

double filterSensibility = 5.0 // % percentage

var myBooleanFilteredTimeSeries = myTimeSeries.Pairwise().Select(kvp => (kvp.Value.Item2 / kvp.Value.Item1) * 100 < filterSensibility);

在这里我可以写我想要的关系! (见问题)然后根据我之前发布的时间序列(示例)得到:

myBooleanFilteredTimeSeries = [FALSE;错误的;错误,正确;错误...]

TRUE 表示此值有噪声!所以我只得到 FALSE 布尔值:

 var myDateKeysModel = from kvp in myBooleanFilteredTimeSeries where kvp.Value == false select kvp;

我根据上一个时间序列创建了一个框架:

myCleanDateTimeKeysFrame = Frame.FromRecords(myDateKeysModel);

最后,我将原始(嘈杂的)时间序列添加到之前创建的帧中:

myCleanDateTimeKeysFrame.AddColumn("Column Title", myOrginalTimeSeries);

...瞧瞧!