快速列子集选择

时间:2015-04-08 09:23:42

标签: matlab cell

为每列选择预定义子集并将所有内容存储在单元格中的最快方法是什么?

这意味着我有一个双矩阵

DAT
尺寸n x m

和选择矩阵

SEL
尺寸为n x m的

。矩阵'SEL'是一个逻辑矩阵。

现在我想根据'SEL'为'DAT'的每一列选择列。

一种可能的方法显然是:

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

是否可能加快速度?

更新: 所有的矩阵都很稀疏 2. n = 1800000,m = 800

2 个答案:

答案 0 :(得分: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的数据,那么性能提升会更加明显!

答案 1 :(得分: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});