Help us understand the problem. What is going on with this article?

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

More than 1 year has passed since last update.

使用環境

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より
- how can I count the number of elements on a vector?
- Can I use UNIQUE to get a count of the number of times each element is repeated?
- How can I count the number of elements of a given value in a matrix?
を参照しました。

eigs
MATLAB の中の人 MathWorks Japan アプリケーションエンジニア部 データ解析チームリーダー。 公式ブログも書いています。MATLAB の使い方に困ったら MATLAB Answers もどうぞ。 All comments are mine alone and do not necessarily reflect those of my employers.
https://blogs.mathworks.com/japan-community/
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away