10
5

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

【MATLAB】配列内のユニークな要素、それぞれの数を数える方法

Last updated at Posted at 2017-08-23

使用環境

MATLAB R2017a

課題

例えば

v = [1,2,3,4,2,2,1];

という配列があった時に、1が2つ、2が3つ、、というように数え上げるとします。

意外と分かりやすい名前の関数がなく、泣く泣くforループでプログラムを組んでいました。こんな感じ。

v = [1,2,3,4,2,2,1];
vq = unique(v);
N = length(vq);

numvq = zeros(N,1);
tic
for ii=1:N
    numvq(ii) = sum(v==ii);
end
toc

やりたいことは実現できているんですが、配列数が巨大になると時間がかかるし、なにより美しくない
そこで、forループを使わずに実現できないかと調べた3つの方法を紹介します。

それぞれの方法で計算にかかった時間の目安として、手元のlaptopで tic/toc を使用して計測した時間を書いておきます。

関数名 処理時間
arrayfun 0.16 秒
accumarray 0.0013 秒
histcounts 0.0016 秒

for ループ 使用した場合は 0.18 秒程度でした。accumarray 関数いいですね。

実行時間計測のために、1から1000までの整数をランダムに持つ 10万 x 1 のベクトル v を作って、それぞれの整数が何回現れるかを求めてみました。

以下それぞれのコードです。

arrayfun 関数

N = 1e5;
v = randi(1000,N,1);
numvq = arrayfun(@(x) sum(v == x), unique(v));

これは for ループは避けられましたが、速度はいまいち。

accumarray 関数

N = 1e5;
v = randi(1000,N,1);
numvq = accumarray(v,1);

関数の挙動を理解するのに時間がかかりましたが、計算速度はこれが最も速かった。

histcounts 関数

N = 1e5;
v = randi(1000,N,1);
numvq = histcounts(v,'BinMethod','integers');

histcounts 関数は R2014b で導入された比較的新しい関数ですが、このオプションは意識したことありませんでした。

参考

Q&AサイトMATLAB Answersより

10
5
3

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
10
5

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?