如何在linq中对不同的分组执行多个单独的聚合?
例如,我有一张桌子:
UNO YOS Ranking Score
123456 1 42 17
645123 3 84 20
我想对此数据进行分组和未分组的一组聚合,例如:
var grouped = table.GroupBy(x => x.score )
.Select(x => new
{
Score = x.Key.ToString(),
OverallAverageRank = x.Average(y => y.Ranking),
Year1RankAvg = x.Where(y => y.YOS == 1).Average(y => y.Ranking),
Year2RankAvg = x.Where(y => y.YOS == 2).Average(y => y.Ranking)
//...etc
});
我还想对相同的切片和整个数据执行不同的汇总(标准差)。
我无法弄清楚如何同时对YOS进行分组和不分组,尽管编译起来很好,但是在运行时,如果任何YOS平均值是,我都会得到“序列不包含任何元素”。内。
答案 0 :(得分:0)
像任何编程一样,当您有一系列相似的项目时,请使用一个集合。在这种情况下,我将其保留为IEnumerable
,但可以根据需要将其设置为List
或Dictionary
的{{1}}。
YOS
如果您需要填写从1到最大(或其他一些数字)的年份范围,则可以修改答案:
var ans = table.GroupBy(t => t.Score)
.Select(tg => new {
Score = tg.Key,
OverallAverageRank = tg.Average(t => t.Ranking),
YearRankAvgs = tg.GroupBy(t => t.YOS).Select(tyg => new { YOS = tyg.Key, RankAvg = tyg.Average(t => t.Ranking) })
});
如果您愿意,可以修改原始的var ans2 = ans.Select(soryr => new {
soryr.Score,
soryr.OverallAverageRank,
YearRankDict = soryr.YearRankAvgs.ToDictionary(yr => yr.YOS),
YearMax = soryr.YearRankAvgs.Max(yr => yr.YOS)
})
.Select(soryr => new {
Score = soryr.Score,
OverAverageRank = soryr.OverallAverageRank,
YearRankAvgs = Enumerable.Range(1, soryr.YearMax).Select(yos => soryr.YearRankDict.ContainsKey(yos) ? soryr.YearRankDict[yos] : new { YOS = yos, RankAvg = 0.0 }).ToList()
});
以将ans
返回为RankAvg
,并在添加缺失年份时将double?
替换为null
。