2015-04-08 354 views
2

什麼是爲每列選擇預定義子集並將所有內容存儲在單元格中的最快方法?快速列子集選擇

這意味着我的維數n×m個

雙矩陣

DAT 

和的維數n×m個選擇矩陣

SEL 

。矩陣'SEL'是一個邏輯矩陣。

現在我想根據'SEL'爲'DAT'的每列選擇列。

一種可能的方式是明確提出:

arrayfun(@(idx) DAT(idx,SEL(idx,:)),(1:n)','uni',false); 

是否可能加快這?

更新: 1.所有矩陣是稀疏 2. N = 180萬,M = 800

回答

2

這可能是一個替代辦法 -

%// Since we are storing elements from each row, we need to transpose them, 
%// so that we could select elements from SEL along the first row, then second 
%// row and so on. 
DAT_t = DAT.';   %//' 
allvals = DAT_t(SEL.'); %//' 

%// Create an ID array to be used with ACCUMARRAY later on 
cumlens = cumsum(sum(SEL,2)); 
id = zeros(cumlens(end),1); %// Faster with: id(cumlens(end),1)=0; 
id([1 ; cumlens(1:end-1)+1])=1; 

%// Finally use ACCUMARRAY for creating cells of output cell array based on 
%// IDs from "id" and data from DAT 
outc = accumarray(cumsum(id),allvals,[],@(x) {x}); 

顯然,一些快速運行試驗證實,這種提出的方法通過非常大的輸入數據大小提高了邊際性能。因此,8000 x 8000大小的輸入陣列,當timeit定時運行時間分別爲 -

time_arrayfun = 
    1.5076 
time_accum = 
    1.4776 

而且,請注意,大量的時間都花在換位DAT & SEL得到allvals,因爲我們只會做在這種情況下爲allvals = DAT(SEL)。因此,如果您要存儲每列的數據而不是每行DAT,則性能提升將更加明顯!

+0

如何運行它時,SEL和DAT稀疏?兩個矩陣都很大...... – Graph4Me

+0

@ Graph4Me在'accumarray'內使用'full(allvals)'。 – Divakar

+0

工程,比我的方法快5秒。 (10秒對15秒) – Graph4Me

2

這是另一種方法。對於列:

s = bsxfun(@times, SEL, 1:size(SEL,2)); 
result = accumarray(nonzeros(s), DAT(SEL), [], @(x) {x}); 

對於行,只是調換DATSEL

DAT = DAT.'; 
SEL = SEL.'; 
s = bsxfun(@times, SEL, 1:size(SEL,2)); 
result = accumarray(nonzeros(s), DAT(SEL), [], @(x) {x}); 
+0

如何在SEL和DAT稀疏時運行它? – Graph4Me

+1

@ Graph4Me在'accumarray'裏面使用'full(DAT(SEL))'我想。 – Divakar

+0

工程,比我的方法快5秒。 (10秒對15秒) – Graph4Me