0

我有以下问题:我有一个矩阵,20 x 1000我想把它分成四个大小的子矩阵20 x 250

之后,我想对每个子矩阵进行操作,假设我有一个P长度等于子矩阵数量 4 的向量。

P= [ 3 4 5 6] 

我打算为每个子矩阵(A)做的事情如下:

对于第一个子矩阵: A(:,1:P(1))=1

以及第二个子矩阵:A(:,1:P(2))=1等等。

没有循环我怎么能做到这一点?

4

1 回答 1

0

一种矢量化方法可能是 和 的组合cumsumbsxfun但这可能会占用一些内存 -

blocksize = 250;
valid_idx = bsxfun(@le,[1:max(P)],P');
idx_mat = bsxfun(@plus,cumsum(valid_idx,2),[0:numel(P)-1]'*blocksize);
A(:,idx_mat(valid_idx)) = 1; %// You can replace this with "A(:,unique(idx_mat))=1;"

另一种略有不同的方法 -

blocksize = 250;
maxP = max(P);
valid_idx = bsxfun(@le,[1:maxP],P');
idx_mat = bsxfun(@plus,[0:numel(P)-1]'*blocksize,1:maxP);
A(:,idx_mat(valid_idx))=1;

请注意,要真正看到矢量化解决方案的好处,您需要在原始循环代码进行大量迭代时使用它。否则,与设置矢量化方法的准备工作相关的开销将是一种浪费。因此,我假设您的实际案例不仅仅涉及 4 个子矩阵。


另一种cumsum基于方法,这个方法一定很有趣,甚至可能被证明是最好的——

blocksize = 250;

%//Get monotonically increasing labels within each group, defined by limits from idx
array1 = zeros(1,sum(P));
grp_starts = cumsum(P(1:end-1))+1;
array1(grp_starts) = P(1:end-1);
grp_labels = [1:numel(array1)] - cumsum(array1);

%// Get offsetted indices
array2 = zeros(1,sum(P));
array2(grp_starts) = blocksize;
offsetted_grp_labels = grp_labels + cumsum(array2);

A(:,offsetted_grp_labels)=1; %// perform the operation(s)
于 2014-10-22T03:22:24.213 回答