我有一个linq语句,它平均DataTable中的行并将它们显示在图表上,按日期和时间分组。
有一个大问题:由于一天中的特定时间根本没有发生任何事情,因此返回了许多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"]),
};
我不知道这是否可行,所以我想我会问 - 有没有办法在没有0的情况下做平均值?
谢谢!
答案 0 :(得分:4)
当然你可以过滤掉零:
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(),
如果您的结果集(Where
之后)可能为空,则可能需要致电DefaultIfEmpty
。
AvgItem1 = g.Select(x => (int)x["Item1"]).Where(x => x != 0).DefaultIfEmpty(0).Average(),
这将返回非空结果集,以便Average
能够使用它。
答案 1 :(得分:1)
由于你有很多重复,你可以考虑将你的平均逻辑重构为一个单独的方法或匿名函数:
Func<IEnumerable<YourClass>, string, double> avg =
(g, name) => g.Select(x => (int)x[name]).Where(x => x != 0).Average();
var results = from row2 in fiveDayDataTable.AsEnumerable()
group row2 by ((DateTime)row2["TheDate"]).TimeOfDay
into g
select new
{
Time = g.Key,
AvgItem1 = avg(g, "Item1"),
AvgItem2 = avg(g, "Item2"),
AvgItem3 = avg(g, "Item3"),
AvgItem4 = avg(g, "Item4"),
AvgItem5 = avg(g, "Item5"),
};
答案 2 :(得分:0)
在Where
之前的每个查询中添加Average
,确保该项目不等于零。