bsxfun
ベースのアプローチ -
A = [0.1 0.2 0.3 0.4 0.5]
r = [5 2 3 2 1]
repeats = bsxfun(@le,[1:max(r)]',r) %//' logical 2D array with ones in each column
%// same as the repeats for each entry
A1 = A(ones(1,max(r)),:) %// 2D matrix of all entries repeated maximum r times
%// and this resembles your repmat
out = A1(repeats) %// desired output with repeated entries
それは本質的にツーライナーになる可能性があります-
A1 = A(ones(1,max(r)),:);
out = A1(bsxfun(@le,[1:max(r)]',r));
出力 -
out =
0.1000
0.1000
0.1000
0.1000
0.1000
0.2000
0.2000
0.3000
0.3000
0.3000
0.4000
0.4000
0.5000
ベンチマーク
これまでに紹介したソリューションについて、いくつかのベンチマーク結果が生成される可能性があります。
ベンチマーク コード - ケース I
%// Parameters and input data
N = 4000;
max_repeat = 4000;
A = rand(1,N);
r = randi(max_repeat,1,N);
num_runs = 10; %// no. of times each solution is repeated for better benchmarking
disp('------------------- With arrayfun')
tic
for k1 = 1:num_runs
Anew = arrayfun(@(x) repmat(A(x), r(x), 1), 1:numel(A), 'uni', 0);
Anew = vertcat(Anew{:});
end
toc, clear Anew
disp('------------------- With cumsum')
tic
for k1 = 1:num_runs
B(cumsum(r) + 1) = 1;
idx = cumsum(B) + 1;
idx(end) = [];
out1 = A(idx);
end
toc,clear B idx out1
disp('------------------- With bsxfun')
tic
for k1 = 1:num_runs
A1 = A(ones(1,max(r)),:);
out2 = A1(bsxfun(@le,[1:max(r)]',r));
end
toc
結果
------------------- With arrayfun
Elapsed time is 2.198521 seconds.
------------------- With cumsum
Elapsed time is 5.360725 seconds.
------------------- With bsxfun
Elapsed time is 2.896414 seconds.
ベンチマーク コード - ケース II [データサイズは大きいが r の最大値は小さい]
%// Parameters and input data
N = 10000;
max_repeat = 1000;
結果
------------------- With arrayfun
Elapsed time is 2.641980 seconds.
------------------- With cumsum
Elapsed time is 3.426921 seconds.
------------------- With bsxfun
Elapsed time is 1.858007 seconds.
ベンチマークからの結論
の場合は進むべき道のように思えcase I
ますが、の場合は選択の武器かもしれません。したがって、扱っているデータのタイプによって、どのアプローチを採用するかが実際に決まるようです。arrayfun
Case II
bsxfun