繁体   English   中英

在C#和ILNumerics与Matlab中最有效的矩阵聚合方式

[英]Most efficient way of matrix aggregation in c# and ILNumerics vs Matlab

我有一个大矩阵(30000 x 500),一列表示未来3年的每小时数据,每列是不同的情况,即我有500个价格情况,其中行中的每个单元格都具有相同的时间戳。

我需要在时间轴上进行汇总,因此如果每天我都需要制作一个(30000 / nrdays x 500),每月(30000 / nrmonths x 500)矩阵,并且显然还要保留正确的日期。

在matlab中,我创建了一个每天或每个月都有唯一编号的索引,然后使用以下方法遍历各列:

accumarray(idx,price(:,i),[numel(unique(idx)) 1], @mean)

如果我想在C#中执行此操作,最好的方法是什么?

以下是我到目前为止的内容:

public class matrixwihtdates
    {
        public DateTime dats;
        public ILArray<double> nums;
    }
    public class endres
    {
        public string year;
        public string month;
        public string day;
        public ILArray<double> nums;
    }

    public static List<endres> aggrmatrix(ILArray<double> origmatrix, DateTime std, DateTime edd)
    {
        var aggrmatr = new List<matrixwihtdates>();
        for (int i = 0; i < origmatrix.Length; i++) 
        {
            aggrmatr.Add(new matrixwihtdates
            {
                dats = std.AddHours(i),
                nums = origmatrix[i, "full"],
            });
        }

        return aggrmatr.GroupBy(a => new { yr = a.dats.Year, mt = a.dats.Month })
            .Select(g => new endres { 
             year = g.Key.yr.ToString(), 
             month = g.Key.mt.ToString(), 
             nums = ILMath.mean(g.Select(a => a.nums).ToArray(),1) }).ToList();


    }

关键问题是,我不知道如何对LINQ语法中的每一列求平均值,以便返回向量(1x500)。 还是不应该使用LINQ? 我上面的最后一行不起作用。

更新:

我添加了一个不带LINQ的命令式版本,这似乎可行,但仍然有些笨拙。

        public static List<ILArray<double>> aggrmatrixImp(ILArray<double> origmatrix, DateTime std)
    {
        List<ILArray<double>> aggrmatr = new List<ILArray<double>>();
        ILArray<double> tempmatrix;
        int startindicator = 0;
        int endindicator = 0;
        int month = std.Month;
        for (int i = 0; i < origmatrix.Length; i++)
        {
            if (std.AddHours(i).Month != month)
            {
                endindicator = i - 1;
                tempmatrix = origmatrix[ILMath.r(startindicator, endindicator), ILMath.r(0, ILMath.end)];
                aggrmatr.Add(ILMath.mean(tempmatrix, 1));
                startindicator = i;
                month = std.AddHours(i).Month;
            }
        }
        return aggrmatr;
    }

我仍然想使LINQ版本正常工作。

更新2

我考虑了Haymo的建议,这是另一个快两倍的版本。

public static ILArray<double> aggrmatrixImp2(ILArray<double> origmatrix, DateTime firstdateinfile, DateTime std, DateTime edd)
    {
        int nrmonths = ((edd.Year - std.Year) * 12) + edd.Month - std.Month;
        ILArray<double> aggrmatr = ILMath.zeros(nrmonths,500);
        int startindicator = std.Date.Subtract(firstdateinfile.Date).Duration().Days*24;
        int endindicator = 0;
        DateTime tempdate = std.AddMonths(1);
        tempdate = new DateTime(tempdate.Year, tempdate.Month, 1);
        for (int i = 0; i < nrmonths; i++)
        {
                endindicator = tempdate.Date.Subtract(std.Date).Duration().Days * 24-1;
                aggrmatr[i, ILMath.full] = ILMath.mean(origmatrix[ILMath.r(startindicator, endindicator), ILMath.full], 1);
                tempdate = tempdate.AddMonths(1);
                startindicator = endindicator+1;               
        }
        return aggrmatr;
    }

我没有可用的LINQ版本,但我怀疑它会更快。

您的更新版本更适合ILNumerics中处理数组的方式。

对LINQ和ILNumerics.ILArray<T>所述IEnumerable<T>其被用于枚举的ILArray<T>过在列主顺序的所有元素进行迭代。 参见此处: http : //ilnumerics.net/blog/ilnumerics-and-linq/

ILNumerics已针对您在问题更新中使用的命令式,面向数组的版本进行了优化。 如果您仍然决定使用Linq,建议您手动在Linq语句中进行汇总,而不要依赖ILMath.mean

您可以尝试按如下所示(随机顺序)从更新中优化第二个示例:

1)将结果保存在矩阵( ILArray<double> aggrmatr )中,而不是List<ILArray<double>> 如果还要存储日期,也可以使用ILCell 但是您的示例仅存储汇总的数字。 因此, ILArray<double>就足够了。

2)预分配结果ILArray<double>并遍历其行(而不是遍历origmatrix的行)-恰好一次 结果行数应该事先知道,对吧? 至少如果日期行表示日期/时间,则可以根据tempmatrix中的当前行计算开始和结束指示符,并像以前一样使用它们。

3)使用ILMath.full":"表示子ILMath.full表达式中的完整尺寸。

4)使用ILNumerics函数规则 您的矩阵足够大,因此由于内存池和更有效的并行化,很有可能会加快速度。

5)将函数表示在从ILMath派生的类中,可以通过省略ILMath来带来更好的语法ILMath. 所有表达式(如ILMath.r(...ILMath.mean

另外,将ILArray用作类属性时要记住的一些规则(如您的第一个示例)请参见: http : //ilnumerics.net/ClassRules.html

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM