按两列分组并根据其中一列计算累计值

问题描述

请考虑以下列表:

List<Data> lst = new List<Data>
{
    new Data() { Id = 1,Val1 = 100 },new Data() { Id = 1,Val1 = 200 },Val1 = 300 },new Data() { Id = 2,new Data() { Id = 3,};

然后是此代码:

decimal Cumulative_Probability = 0;
var Result1 = (lst.OrderBy(o => o.Id).GroupBy(x => new { x.Val1 })
    .Select(y => new
    {
        y.Key.Val1,Probability = (Convert.ToDecimal(y.Count()) / lst.Count),Cumulative_Probability = (Cumulative_Probability = 
            Cumulative_Probability + 
            (Convert.ToDecimal(y.Count()) / lst.Count))
    })).OrderBy(o => o.Val1).ToList();

此代码可以正常工作,并且Cumulative_Probability的计算正确。

现在请考虑以下代码:

decimal Cumulative_Probability2 = 0;
var Result2 = (lst.OrderBy(o => o.Id).GroupBy(x => new { x.Id,x.Val1 })
    .Select(y => new
    {
        y.Key.Id,y.Key.Val1,Probability = (Convert.ToDecimal(y.Count()) 
            / lst.Where(o => o.Id == y.Key.Id).Count()),Cumulative_Probability = (Cumulative_Probability2 = 
            Cumulative_Probability2 + 
            (Convert.ToDecimal(y.Count()) / 
            lst.Where(o => o.Id == y.Key.Id).Count()))
    })).OrderBy(o => o.Id).ThenBy(o => o.Val1).ToList();

此代码生成以下结果:

enter image description here

您可以看到在每个组中正确计算出Probability,但没有Cumulative_Probability。我想计算每个 Id 组中的Cumulative_Probability(组记录首先按Id,然后按Val1),并且Cumulative_Probability2不在每个组中重置。如何计算每个组中的Cumulative_Probability

谢谢


编辑1)

我想要这个结果:

 Id             Val1             Probability       Cumulative_Probability 
 -------------------------------------------------------------------------
 1              100                0.16                 0.16
 1              200                0.66                 0.82
 1              300                0.16                 0.98
 2              100                0.33                 0.33
 2              200                0.66                 0.66
 ... 

解决方法

我设法借助扩展方法来做到这一点,该方法累积了累积概率以及一些嵌套的next-redux-wrapper。我敢肯定一定有一种更简单的方法,但是我正在努力寻找答案。

扩展名是:

GroupBy

完成的代码如下:

public static class EnumerableExtensions
{
    public static IEnumerable<TResult> Accumulate<TSource,TAccumulate,TResult>(
        this IEnumerable<TSource> source,TAccumulate seed,Func<TAccumulate,TSource,(TAccumulate,TResult)> accumulator)
    {
        var acc = seed;
        foreach(TSource value in source)
        {
            var (newSeed,newSource) = accumulator.Invoke(acc,value);
            yield return newSource;
            acc = newSeed;
        }
    }
}

实时示例:https://dotnetfiddle.net/dvW1qo

,

此代码有效:

var Result2 = (from a in lst.OrderBy(o => o.Id)
               group a by new { a.Id,a.Val1 } into grp
               select new
               {
                   grp.Key.Id,grp.Key.Val1,Probability = (Convert.ToDecimal(grp.Count()) / lst.Where(o => o.Id == grp.Key.Id).Count()),Cumulative_Probability = (from b in lst.Where(o => o.Id == grp.Key.Id && o.Val1 <= grp.Key.Val1)
                                             group b by new { b.Val1 } into grp2
                                             select new
                                             {
                                                 Probability2 = (Convert.ToDecimal(grp2.Count()) / lst.Where(o => o.Id == grp.Key.Id).Count())
                                             }).Sum(o => o.Probability2)
                }).OrderBy(o => o.Id).ThenBy(o => o.Val1).ToList();

相关问答

错误1:Request method ‘DELETE‘ not supported 错误还原:...
错误1:启动docker镜像时报错:Error response from daemon:...
错误1:private field ‘xxx‘ is never assigned 按Alt...
报错如下,通过源不能下载,最后警告pip需升级版本 Requirem...