Jas*_*ges 34 c# linq aggregate-functions
我试图了解如何使用LINQ按时间间隔对数据进行分组; 然后理想地聚合每个组.
查找具有明确日期范围的众多示例,我正在尝试按时段分组,例如5分钟,1小时,1天.
例如,我有一个用Date包装DateTime的类:
public class Sample
{
public DateTime timestamp;
public double value;
}
Run Code Online (Sandbox Code Playgroud)
这些观察结果包含在List集合中的一系列中:
List<Sample> series;
Run Code Online (Sandbox Code Playgroud)
因此,按小时分组和按平均值计算总值,我正在尝试执行以下操作:
var grouped = from s in series
group s by new TimeSpan(1, 0, 0) into g
select new { timestamp = g.Key, value = g.Average(s => s.value };
Run Code Online (Sandbox Code Playgroud)
这基本上是有缺陷的,因为它将TimeSpan本身分组.我无法理解如何在查询中使用TimeSpan(或表示间隔的任何数据类型).
Bro*_*ass 45
您可以将时间戳舍入到下一个边界(即过去最接近最近的5分钟边界)并将其用作分组:
var groups = series.GroupBy(x =>
{
var stamp = x.timestamp;
stamp = stamp.AddMinutes(-(stamp.Minute % 5));
stamp = stamp.AddMilliseconds(-stamp.Millisecond - 1000 * stamp.Second);
return stamp;
})
.Select(g => new { TimeStamp = g.Key, Value = g.Average(s => s.value) })
.ToList();
Run Code Online (Sandbox Code Playgroud)
以上通过在分组中使用修改的时间戳来实现,其将分钟设置为前5分钟边界并移除秒和毫秒.当然,相同的方法可以用于其他时间段,即小时和天.
编辑:
基于这个组成的样本输入:
var series = new List<Sample>();
series.Add(new Sample() { timestamp = DateTime.Now.AddMinutes(3) });
series.Add(new Sample() { timestamp = DateTime.Now.AddMinutes(4) });
series.Add(new Sample() { timestamp = DateTime.Now.AddMinutes(5) });
series.Add(new Sample() { timestamp = DateTime.Now.AddMinutes(6) });
series.Add(new Sample() { timestamp = DateTime.Now.AddMinutes(7) });
series.Add(new Sample() { timestamp = DateTime.Now.AddMinutes(15) });
Run Code Online (Sandbox Code Playgroud)
我为我制作了3组,其中一组分组时间戳为3:05,一组为3:10,另一组为下午3:20(您的结果可能会根据当前时间而有所不同).
Hen*_*man 11
您需要一个对时间戳进行舍入的函数.就像是:
var grouped = from s in series
group s by new DateTime(s.timestamp.Year, s.timestamp.Month,
s.timestamp.Day, s.timestamp.Hour, 0, 0) into g
select new { timestamp = g.Key, value = g.Average(s => s.value };
Run Code Online (Sandbox Code Playgroud)
适用于每小时的垃圾箱.请注意,结果中的时间戳现在将是DateTime,而不是TimeSpan.
我在这场比赛上的比赛已经很晚了,但是我在寻找其他东西的时候遇到了这个问题,我觉得我有更好的方法.
series.GroupBy (s => s.timestamp.Ticks / TimeSpan.FromHours(1).Ticks)
.Select (s => new {
series = s
,timestamp = s.First ().timestamp
,average = s.Average (x => x.value )
}).Dump();
Run Code Online (Sandbox Code Playgroud)
这是一个linqpad程序示例,您可以进行验证和测试
void Main()
{
List<Sample> series = new List<Sample>();
Random random = new Random(DateTime.Now.Millisecond);
for (DateTime i = DateTime.Now.AddDays(-5); i < DateTime.Now; i += TimeSpan.FromMinutes(1))
{
series.Add(new UserQuery.Sample(){ timestamp = i, value = random.NextDouble() * 100 });
}
//series.Dump();
series.GroupBy (s => s.timestamp.Ticks / TimeSpan.FromHours(1).Ticks)
.Select (s => new {
series = s
,timestamp = s.First ().timestamp
,average = s.Average (x => x.value )
}).Dump();
}
// Define other methods and classes here
public class Sample
{
public DateTime timestamp;
public double value;
}
Run Code Online (Sandbox Code Playgroud)