使用 Linq 求平均值,同时完全忽略 0

C S*_*ith 2 c# linq datatable average

我有一个 linq 语句,它对 DataTable 中的行进行平均并将它们显示在图表上,按日期和时间分组。

有一个大问题:由于一天中的特定时间根本没有任何事情发生,因此返回了许多 0 值。这些正在扭曲我的平均值

一天中的不同时间在不同的列中可能有 0,所以我不能只删除列中带有 0 的每一行(干净地),因为我最终会在数据表中没有剩余的行,或者至少我不能在任何情况下都想一个干净的方法来做到这一点。

这就是我所拥有的:

            var results = from row2 in fiveDayDataTable.AsEnumerable()
                          group row2 by ((DateTime)row2["TheDate"]).TimeOfDay
                              into g
                              select new
                              {
                                  Time = g.Key,
                                  AvgItem1 = g.Average(x => (int)x["Item1"]),
                                  AvgItem2 = g.Average(x => (int)x["Item2"]),
                                  AvgItem3 = g.Average(x => (int)x["Item3"]),
                                  AvgItem4 = g.Average(x => (int)x["Item4"]),
                                  AvgItem5 = g.Average(x => (int)x["Item5"]),
                              };
Run Code Online (Sandbox Code Playgroud)

我不知道这是否可能,所以我想我会问 - 有没有办法在没有 0 的情况下做平均值?

谢谢!

p.s*_*w.g 5

当然你可以过滤掉零:

AvgItem1 = g.Select(x => (int)x["Item1"]).Where(x => x != 0).Average(),
AvgItem2 = g.Select(x => (int)x["Item2"]).Where(x => x != 0).Average(),
AvgItem3 = g.Select(x => (int)x["Item3"]).Where(x => x != 0).Average(),
AvgItem4 = g.Select(x => (int)x["Item4"]).Where(x => x != 0).Average(),
AvgItem5 = g.Select(x => (int)x["Item5"]).Where(x => x != 0).Average(),
Run Code Online (Sandbox Code Playgroud)

如果您的结果集(在 之后Where)可能为空,您可能需要调用DefaultIfEmpty.

AvgItem1 = g.Select(x => (int)x["Item1"]).Where(x => x != 0).DefaultIfEmpty(0).Average(),
Run Code Online (Sandbox Code Playgroud)

这将返回一个非空的结果集,因此您Average将能够使用它。