我有一系列带时间戳的数据点,我希望按任意Timepsan值进行分组,
所以我想做一些像:
var span = Timespan.FromMinutes(5);
var grouped = from dataPoint in data
group dataPoint by dataPoint.ThisISWhereIGetStuck(span) into argregateData
select new {
Avg = argregateData.Average(x => x.Counter),
Span = argregateData.Key.SpanStartTime //or some such
};
使用linq可以吗?
答案 0 :(得分:0)
(假设我已经理解你了......)
嗯,一个简单的选择是:
var span = Timespan.FromMinutes(5);
var grouped = from dataPoint in data
group dataPoint by GroupTime(dataPoint.SomeDateTime, span)
into aggregateData
select new {
Avg = aggregateData.Average(x => x.Counter),
Start = aggregateData.Key
};
...
private static DateTime GroupTime(DateTime dateTime, TimeSpan span)
{
long ticks = span.Ticks;
return new DateTime((dateTime.Ticks / ticks) * ticks);
}
这比效率低,请注意 - 更有效的版本是:
var span = Timespan.FromMinutes(5);
long ticks = span.Ticks;
var grouped = from dataPoint in data
group dataPoint by dataPoint.SomeDateTime.Ticks / ticks
into aggregateData
select new {
Avg = aggregateData.Average(x => x.Counter),
Start = new DateTime(aggregateData.Key * ticks)
};
如果按(例如)3分22秒进行分组,你会得到“有趣”的结果...基本上这段代码在DateTime.MinValue
开始了...
答案 1 :(得分:0)
@Jon - 如果按任意间隔进行分组,我不确定结果是否很奇怪,是不是只是某些存储桶未被填充?如果您也捕获了桶号,您可以看到我的意思:
Module Module1
Class DataPoint
Property TimeStamp As DateTime
Property Counter As Integer
Public Overloads Function ToString() As String
Return String.Format("{0} {1}", TimeStamp.ToString("yyyy-MM-dd HH:mm:ss"), Counter)
End Function
Public Sub New(timeStamp As DateTime, counter As Integer)
Me.TimeStamp = timeStamp
Me.Counter = counter
End Sub
End Class
Sub Main()
Dim data As New List(Of DataPoint)
Dim baseTime = DateTime.UtcNow
Dim rand As New Random
' make some random data, possibly with timestamps out of order
For i = 0 To 29
data.Add(New DataPoint(baseTime + TimeSpan.FromSeconds(i * 17 + rand.Next(0, 30)), rand.Next(0, 101)))
Next
' show the data for inspection
For Each d In data
Console.WriteLine(d.ToString)
Next
' make the buckets smaller than the expected interval between data
Dim bucketSize = TimeSpan.FromMinutes(0.1)
Dim grps = From datum In data
Group datum By bnr = (datum.TimeStamp.Ticks - baseTime.Ticks) \ bucketSize.Ticks
Into buckets = Group
Select Avg = buckets.Average(Function(x) x.Counter),
BucketStart = buckets.First,
BucketNumber = bnr,
Count = buckets.Count
Console.WriteLine(grps.Count.ToString & " buckets.")
' show that not all buckets are filled/created
For Each b In grps
Console.WriteLine(String.Format("{0,3} {1,3} {2} {3}", b.BucketNumber, b.Count, b.BucketStart.TimeStamp.ToString("yyyy-MM-dd HH:mm:ss"), Math.Round(b.Avg, 2)))
Next
Console.ReadLine()
End Sub
End Module