簡體   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