如何在 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);
...瞧瞧!
我正在处理来自传感器的数据。有时这些传感器会断电和断电,因此我可以在一个帧中有以下类型的时间序列,我们称之为 "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);
...瞧瞧!