簡體   English   中英

用於3D矩陣的Matlab Accumarray

[英]Matlab Accumarray for 3D matrix

我真的希望文檔在Matlab中將Accumarray用於ND尺寸矩陣時更加清晰。 無論如何,我在這里很困惑,正在尋找一些建議。 這是挑戰:

我有一個3D數據矩陣。

  • ROWS是個別河流
  • 欄是觀測日期
  • PAGES是數據收集的時間間隔

對於此示例,我們假設每個觀測值都是每5分鍾間隔流經儀表的水量。 但是,我現在希望將數據重新采樣為N分鍾的間隔(顯然是5的倍數)。 讓我們選擇NMINS = 15。

因此,我想做的是找出NMINS分鍾間隔內的水量總和。 也就是說,ROWS和COLUMNS不會更改,但是PAGES的尺寸和值將被抽取/匯總。

我可以獲取頁面的分組值。 也就是說,我需要分組的值。 如果一天只有一條河,那沒問題。 但是,我有數百天和數十條河流。

我已經走了這么遠:

創建測試時間矢量

NMINS   = 15; % Bucket by every 15 mins or 20, etc.
N5MINS  = 5 * 12 * 24 * 2; % Keep small - Two days of 5 min datenums
dnums   = datenum(2016,3,20,0,0:5:N5MINS,0);
% Trim dnums to start at random time for edge case and keep only mins
mins    = rem(dnums(25:end-30),1)';    % Create column vector

創建用於測試的隨機矩陣

rng(123); % Set seed for reproducibility
X       = randi(100,12,9,length(mins)); % Test matrix

以分鍾為單位查找時間

[~,~,~,H,M] = datevec( mins );
H       = 60 .* (H - H(1));

現在查找與我們的桶相對應的所有時間

idxMIN  = mod( M+H, NMINS )==0;
idxNewP = idxMIN;          % This is used to align the new river matrix
[R,C,P] = size(X);         % We'll drop P and use newP
newP    = sum(idxNewP); % Number of PAGES in final matrix (new)
% Final newX will have dimensions [R,C,newP]

重設分組索引

% Must shift one all as minute intervals represent data UP to that point
% for the actual grouping of data. Test if first bucket is a 
% match and set accordingly
if idxMIN(1)
    idxMIN = [1; idxMIN(1:end-1)]; 
    subs = cumsum(idxMIN);
else 
    idxMIN = [0; idxMIN(1:end-1)];
    subs = cumsum(idxMIN) + 1 ;
end

補充:小組人數將不一致,我不能(很難)做出這種假設。 運行以上步驟后,請考慮以下內容。

tsttbl = table();
tsttbl.dnumstr = datestr(mins(1:5));
tsttbl.Mins    = M(1:5);
tsttbl.subs    = subs(1:5);
tsttbl

輸出顯示第一組的大小為1:

tsttbl = 

    dnumstr     Mins    subs
    ________    ____    ____

     2:00 AM     0      1   
     2:05 AM     5      2   
     2:10 AM    10      2   
     2:15 AM    15      2   
     2:20 AM    20      3  

最后,最終,我需要傳遞自定義函數。 上面是一個玩具示例,可以快速說明問題。 抱歉,我不清楚。

結束添加

這就是我絆倒的地方...

如何設置要在每個頁面上應用的subs值以使用accumarray? 我完全被文檔弄糊塗了。 還是這實際上是錯誤的方法? 為了值得,我正在使用Matlab 2015b。

老實說,任何幫助將不勝感激。

替代解決方案這使我在回家的路上感到震驚 Meshgrid是我的朋友。

一旦運行了上面的單元格(請注意,我更改了矩陣X的大小),我們將為整個矩陣創建索引,其中頁面(即時間)的“索引”由“ subs”中的值給出。 為此,我使用meshgrid。

[days,rivers,pages] = meshgrid(1:C,1:R,subs);
grpvals = [rivers(:) days(:) pages(:)];
tst     = accumarray(grpvals,X(:),[R C newP],@sum);

可能不是最高效的內存,因為我必須本質上創建日期,河流和頁面矩陣,然后最終創建一個包含這些矩陣的新grpvals數組。 但是,它的優勢在於現在我可以使用accumarray並傳遞匿名函數,@ std等。

希望這對別人有幫助!

非常感謝路易斯。

如果所有組的大小都相同

您可以按以下方式進行匯總:

  1. 沿第4維reshape以構建要聚合的組。 現在,第3維是指每個組的元素,第4維是指組。
  2. 沿第3維sum (每個組)。
  3. squeeze現在單一的第3維以恢復3D陣列。

碼:

X = randi(9,2,3,6); %// example data. 3D array.
G = 2; %// group size along 3rd dim. Divides size(X,3)
result = squeeze(sum(reshape(X, size(X,1), size(X,2), G, []), 3));

例如,對於G = 2

X(:,:,1) =
     2     3     9
     4     5     9
X(:,:,2) =
     3     8     2
     6     9     8
X(:,:,3) =
     4     4     4
     1     1     7
X(:,:,4) =
     9     9     8
     2     4     1
X(:,:,5) =
     9     5     9
     3     5     8
X(:,:,6) =
     9     1     3
     5     3     1

result(:,:,1) =
     5    11    11
    10    14    17
result(:,:,2) =
    13    13    12
     3     5     8
result(:,:,3) =
    18     6    12
     8     8     9

一般情況:大小可能不同的組

由於accumarray不適用於多維數組(甚至是矩陣)作為第二個輸入,因此可以沿此答案行使用矩陣乘法。 為此,您需要將3D數組的前兩個維打包為一個維(最后將解壓縮),然后從組索引中構建一個零一矩陣,該矩陣將通過矩陣乘法給出所需的結果。

X = randi(9,2,3,5); %// example data. 3D array.
subs = [1 2 2 1 1]; %// indices of groups. Groups may differ in size, and indices
                    %// need not be sorted
Y = reshape(X, [], size(X,3)); %// reshape into a matrix. Groups are along rows
M = full(sparse(1:numel(subs), subs, 1)); %// indicator matrix from group indices
result = reshape(Y*M, size(X,1), size(X,2), []); %// compute result and reshape 

例如,

X(:,:,1) =
     9     3     8
     6     8     8
X(:,:,2) =
     3     8     3
     7     2     2
X(:,:,3) =
     7     3     6
     2     8     5
X(:,:,4) =
     7     4     5
     8     8     6
X(:,:,5) =
     2     3     2
     2     8     8

subs =
     1     2     2     1     1

result(:,:,1) =
    18    10    15
    16    24    22
result(:,:,2) =
    10    11     9
     9    10     7

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM