LINQ aggregate and group by periods of time

后端 未结 8 2041
醉酒成梦
醉酒成梦 2020-11-28 06:28

I\'m trying to understand how LINQ can be used to group data by intervals of time; and then ideally aggregate each group.

Finding numerous examples with explicit dat

相关标签:
8条回答
  • 2020-11-28 07:22

    You could round the time stamp to the next boundary (i.e. down to the closest 5 minute boundary in the past) and use that as your grouping:

    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();
    

    Above achieves that by using a modified time stamp in the grouping, which sets the minutes to the previous 5 minute boundary and removes the seconds and milliseconds. The same approach of course can be used for other time periods, i.e. hours and days.

    Edit:

    Based on this made up sample input:

    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) });
    

    3 groups were produced for me, one with grouping timestamp 3:05, one with 3:10 and one with 3:20 pm (your results may vary based on current time).

    0 讨论(0)
  • 2020-11-28 07:22

    I'd suggest using new DateTime() to avoid any issues with sub millisecond differences

    var versionsGroupedByRoundedTimeAndAuthor = db.Versions.GroupBy(g => 
    new
    {
                    UserID = g.Author.ID,
                    Time = RoundUp(g.Timestamp, TimeSpan.FromMinutes(2))
    });
    

    With

      private DateTime RoundUp(DateTime dt, TimeSpan d)
            {
                return new DateTime(((dt.Ticks + d.Ticks - 1) / d.Ticks) * d.Ticks);
            }
    

    N.B. I am here grouping by Author.ID as well as the rounded TimeStamp.

    RoundUp function taken from @dtb answer here https://stackoverflow.com/a/7029464/661584

    Read about how equality down to the millisecond doesn't always mean equality here Why does this unit test fail when testing DateTime equality?

    0 讨论(0)
提交回复
热议问题