gpt4 book ai didi

c# - 查找时间序列中的开始和停止

转载 作者:太空宇宙 更新时间:2023-11-03 12:08:01 25 4
gpt4 key购买 nike

我想知道是否有办法使用 linq exp 查找给定时间序列的所有开始和停止窗口(由开始值和结束值分隔)。我知道这可以通过一个正常的循环来实现,但如果可能的话,我喜欢扩展我的知识。

数据存储在“TagData”(List<TagData>)的有序列表中

class TagData
{
public DateTime Timestamp { get; set; }
public string Tag { get; set; }
public double Value { get; set; }
}

数据内容完全交替时的简单方法,例如:

timestamp               | tag       | value
2018-12-01 00:10:00.000 | extrg_01 | 1
2018-12-01 00:15:02.000 | extrg_01 | 0
2018-12-01 00:25:50.000 | extrg_01 | 1
2018-12-01 00:45:11.000 | extrg_01 | 0

此时给定初始值 = 1 和结束值 = 0,结果将是这样的:

timestamp_start         |timestamp_end              | tag       | nrOfSeconds
2018-12-01 00:10:00.000 |2018-12-01 00:15:02.000 | extrg_01 | 302
2018-12-01 00:25:50.000 |2018-12-01 00:45:01.000 | extrg_01 | 1161

但也可能有一些不需要考虑的“脏”数据:

timestamp               | tag       | value
2018-12-01 00:10:00.000 | extrg_01 | 1
2018-12-01 00:12:02.000 | extrg_01 | 1
2018-12-01 00:15:02.000 | extrg_01 | 0
2018-12-01 00:16:01.000 | extrg_01 | 0
2018-12-01 00:25:50.000 | extrg_01 | 1
2018-12-01 00:45:11.000 | extrg_01 | 0

在这种情况下,最终结果不应与第一个示例不同,因为不考虑定义的初始值(在本例中为 = 1)之后的所有值,同样,只有第一个最终值(在本例中为= 0) 将被考虑用于计算。

我忘记添加我试图编辑的 linq 表达式以获得结果:不幸的是,我不明白如何在此 .Zip 中添加 where 条件(如果可能的话)以查找特定值并遵守时间条件以始终找到下一个可用值。

var diffs = tagDataList.Skip(1)
.Zip(tagDataList,
(curr, prev) => new
{
CurrTag = curr.Tag,
CurrValue = curr.Value,
CurrDate = curr.Timestamp,
PrevDate = prev.Timestamp,
DiffToPrev = Math.Abs((curr.Timestamp - prev.Timestamp).TotalSeconds)
})
.ToList();

最佳答案

可能有很多方法可以做到这一点。我会试一试:

我假设您希望分别处理不同的标签。这是我的方法:

  1. 按标签对条目进行分组。
  2. 对于每个组:
    1. 从列表的开头删除所有值为 0 的条目。
    2. 如果有两个或多个相邻条目具有相同的值,则只保留第一个。
      • 现在我们有一个从值 1 开始并在 1 和 0 之间交替的列表。
    3. 将 1 与 0 压缩在一起以计算时间跨度。
  3. 最后将每组的所有结果拉平

我使用了这个测试数据:

var list = new List<TagData> {
new TagData { Timestamp = DateTime.Parse("2018-12-01 00:09:00.000"), Tag = "extrg_01", Value = 0 },
new TagData { Timestamp = DateTime.Parse("2018-12-01 00:10:00.000"), Tag = "extrg_01", Value = 1 },
new TagData { Timestamp = DateTime.Parse("2018-12-01 00:10:00.000"), Tag = "extrg_02", Value = 1 },
new TagData { Timestamp = DateTime.Parse("2018-12-01 00:12:02.000"), Tag = "extrg_01", Value = 1 },
new TagData { Timestamp = DateTime.Parse("2018-12-01 00:15:02.000"), Tag = "extrg_01", Value = 0 },
new TagData { Timestamp = DateTime.Parse("2018-12-01 00:16:01.000"), Tag = "extrg_01", Value = 0 },
new TagData { Timestamp = DateTime.Parse("2018-12-01 00:15:02.000"), Tag = "extrg_02", Value = 0 },
new TagData { Timestamp = DateTime.Parse("2018-12-01 00:25:50.000"), Tag = "extrg_01", Value = 1 },
new TagData { Timestamp = DateTime.Parse("2018-12-01 00:45:11.000"), Tag = "extrg_01", Value = 0 },
new TagData { Timestamp = DateTime.Parse("2018-12-01 00:25:50.000"), Tag = "extrg_02", Value = 1 },
new TagData { Timestamp = DateTime.Parse("2018-12-01 00:45:11.000"), Tag = "extrg_02", Value = 0 },
};

类定义:

class TagData
{
public DateTime Timestamp { get; set; }
public string Tag { get; set; }
public double Value { get; set; }
}

class TagSummary
{
public DateTime TimestampStart { get; set; }
public DateTime TimestampEnd { get; set; }
public string Tag { get; set; }
public TimeSpan TimeSpan => TimestampEnd - TimestampStart;
}

代码:

var summaries =
list.GroupBy(tagdata => tagdata.Tag) // Step (1)
.Select(group => // Step (2)
{
var data = group
.SkipWhile(tagdata => tagdata.Value == 0) // Step (2.1)
.Aggregate(new List<TagData>(), (acc, tagdata) => // Step (2.2)
{
if (acc.LastOrDefault()?.Value != tagdata.Value)
acc.Add(tagdata);
return acc;
});

var ones = data.Where(datatag => datatag.Value == 1);
var zeros = data.Where(datatag => datatag.Value == 0);
var result = ones.Zip(zeros, (startTag, endTag) => { // Step (2.3)
return new TagSummary { TimestampStart = startTag.Timestamp, TimestampEnd = endTag.Timestamp, Tag = startTag.Tag };
});

return result;
})
.SelectMany(x => x); // Step (3)

Console.WriteLine("timestamp_start | timestamp_end | tag | nrOfSeconds");
foreach (var summary in summaries)
Console.WriteLine($"{summary.TimestampStart:yyyy-MM-dd HH:mm:ss} | {summary.TimestampEnd:yyyy-MM-dd HH:mm:ss} | {summary.Tag,-8} | {summary.TimeSpan.TotalSeconds:0}");

输出如您指定的那样:

timestamp_start     | timestamp_end       | tag      | nrOfSeconds
2018-12-01 00:10:00 | 2018-12-01 00:15:02 | extrg_01 | 302
2018-12-01 00:25:50 | 2018-12-01 00:45:11 | extrg_01 | 1161
2018-12-01 00:10:00 | 2018-12-01 00:15:02 | extrg_02 | 302
2018-12-01 00:25:50 | 2018-12-01 00:45:11 | extrg_02 | 1161

关于c# - 查找时间序列中的开始和停止,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53913014/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com