私が見ることができる最良のベクトル化された答えは次のとおりです。
gridx = arrayfun(@(grix)find((grnum(:)==grix) & (value(:)==grvalue(grix)),1),unique(grnum));
しかし、これを「高速な」ベクトル化されたソリューションとは言えません。 arrayfun
本当に便利ですが、一般的にループより速くはありません。
ただし、最速の答えは常にベクトル化されているわけではありません。あなたが書いたようにコードを再実装したが、より大きなデータセットを使用した場合:
nValues = 1000000;
value = floor(rand(nValues,1)*100000);
group = num2cell(char(floor(rand(nValues,1)*4)+'a'));
tic;
[grnum, grname] = grp2idx(group);
grvalue = accumarray(grnum,value,[],@max);
toc;
私のコンピュータは私に0.886秒のtic/toc時間を与えます。(1回限りのpcode生成を避けるために、すべてのtic / tock時間は、ファイルで定義された関数の2回目の実行からのものであることに注意してください。)
「ベクトル化された」(実際にはarrayfun
)1行のgridx計算を追加すると、0.975秒のチック/タック時間が発生します。悪くはありませんが、追加の調査によると、ほとんどの時間が通話に費やされていgrp2idx
ます。
gridx
これを、次のように、計算を含む、ベクトル化されていない単純なループとして再実装すると、次のようになります。
tic
[grnum, grname] = grp2idx(group);
grvalue = -inf*ones(size(grname));
gridx = zeros(size(grname));
for ixValue = 1:length(value)
tmpGrIdx = grnum(ixValue);
if value(ixValue) > grvalue(tmpGrIdx)
grvalue(tmpGrIdx) = value(ixValue);
gridx(tmpGrIdx) = ixValue;
end
end
toc
tic / toc時間は約0.847秒で、元のコードよりわずかに高速です。
これをもう少し進めてみると、ほとんどの場合、セルアレイのメモリアクセスで失われているように見えます。例えば:
tic; groupValues = double(cell2mat(group')); toc %Requires 0.754 seconds
tic; dummy = (cell2mat(group')); toc %Requires 0.718 seconds
最初にグループ名を数値配列として定義すると(たとえば、groupValues
上記で定義したとおりに使用します)、同じコードを使用しても、時間が大幅に短縮されます。
groupValues = double(cell2mat(group')); %I'm assuming this is precomputed
tic
[grnum, grname] = grp2idx(groupValues);
grname = num2cell(char(str2double(grname))); %Recapturing your original names
grvalue = -inf*ones(size(grname));
gridx = zeros(size(grname));
for ixValue = 1:length(value)
tmpGrIdx = grnum(ixValue);
if value(ixValue) > grvalue(tmpGrIdx)
grvalue(tmpGrIdx) = value(ixValue);
gridx(tmpGrIdx) = ixValue;
end
end
toc
これにより、0.16秒のチック/トック時間が生成されます。