2

Aelements を含む値ベクトルがありますi。次に例を示します。

A = [0.1 0.2 0.3 0.4 0.5]; そして、言いますr = [5 2 3 2 1];

ここで、 の値の繰り返しをAnew含む新しいベクトルを作成して、 の最初の項目 が値を持ち、新しいベクトルの長さが になるようにします。したがって:r(i)iAr(1)=5AnewA(1)sum(r)

Anew = [0.1 0.1 0.1 0.1 0.1 0.2 0.2 0.3 0.3 0.3 0.4 0.4 0.5]

forこれは、たとえば を組み合わせた精巧な -loopで実行できると確信していますがrepmat、誰かがこれをよりスムーズな方法で行う方法を知っている可能性はありますか?

4

3 に答える 3

3

まず、インデックス ベクトルを形成することを考えます[1 1 1 1 1 2 2 3 3 3 4 4 5]。ここで定期的な増分に注目すると、cumsum が思い浮かびます。ゼロ ベクトルの正しい位置に 1 を配置することで、これらのステップを得ることができます[1 0 0 0 0 1 0 1 0 0 1 0 1]。そして、入力リストで別のものを実行することで取得できますcumsum終了条件と 1 ベースのインデックスを調整すると、次のようになります。

B(cumsum(r) + 1) = 1;
idx = cumsum(B) + 1;
idx(end) = [];
A(idx)
于 2014-09-26T16:44:43.720 に答える
3

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ますが、の場合は選択の武器かもしれません。したがって、扱っているデータのタイプによって、どのアプローチを採用するかが実際に決まるようです。arrayfunCase IIbsxfun

于 2014-09-26T16:55:23.207 に答える