2013-05-08 8 views
6

のベクトルで2つの番号の組み合わせのユニーク#をカウントする最速の方法2要素との組み合わせ。MATLAB次のような整数のベクトルを考えると整数

この場合、2つの番号の組み合わせは以下のとおりです。

[1 2] (occurs twice) 
[2 3] (occurs once) 
[3 4] (occurs once) 
[4 5] (occurs once) 
[5 1] (occurs once) 

現状では

X = [1 2 3 4 5 1 2]; 
N = length(X) 
X_max = max(X); 
COUNTS = nan(X_max); %store as a X_max x X_max matrix 

for i = 1:X_max 

    first_number_indices = find(X==1) 
    second_number_indices = first_number_indices + 1; 
    second_number_indices(second_number_indices>N) = [] %just in case last entry = 1 
    second_number_vals = X(second_number_indices); 

    for j = 1:X_max 
     COUNTS(i,j) = sum(second_number_vals==j) 
    end 
end 

やっての高速化/スマートに方法はありますが、以下のように、私は現在、MATLABでこれをやっていますこの?

+1

誰かが興味を持っている場合、私が念頭に置いておいてほしいアプリケーションは次のとおりです:X基本的にはマルコフ連鎖のサンプルパスであり、COUNTSは正規化後にCOUNTS(i、j)= P(次の状態= j |現在の状態= i)。 –

+0

良い質問ですが、私はそれが少し誤解を招く方法を見つけました。ユニークな組み合わせの数、つまりそこに存在する組み合わせの数はわかりませんが、各組み合わせの数は分かりません。それ以外の場合、 'unique(A、 'rows')'はあなたの友人でした。 –

答えて

12

は、超高速な方法です:

>> counts = sparse(x(1:end-1),x(2:end),1) 
counts = 
    (5,1)  1 
    (1,2)  2 
    (2,3)  1 
    (3,4)  1 
    (4,5)  1 

あなたは単にフル行列に変換することができます:ここでfull(counts)


accumarrayを使用して同等のソリューションです:

>> counts = accumarray([x(1:end-1);x(2:end)]', 1) 
counts = 
    0  2  0  0  0 
    0  0  1  0  0 
    0  0  0  1  0 
    0  0  0  0  1 
    1  0  0  0  0 
+0

+1:帽子はあなたに、よろしく! –

+4

Nerdgasm、誰ですか?(+1) –

+1

haha​​、この種の質問はかなり頻繁に(マルコフ連鎖との関連で)出てくる。そして、希薄な解決策がしばしば引用される。 – Amro

1

EDIT: @Amroがはるかに優れたソリューションを提供してきました(まあ、ほとんどの場合では、より良いが、私はMaxXが非常に大きく、Xはゼロが含まれている場合は、私の方法は、より良い仕事と疑う - これはのために存在することですゼロは、sparseの使用を除外しますが、大きなMaxXは、accumarrayのアプローチをMaxXのサイズMaxXのマトリックスを作成するときに遅くします。

編集:accumarrayを使用して改善できる点を指摘してくれた@EitanTに感謝します。各ユニークな組み合わせに対応するカウントがCountに格納されている間、すべてのユニークなシーケンシャル2要素の組み合わせは、今、UniqueCombに格納されている

%Generate some random data 
T = 20; 
MaxX = 3; 
X = randi(MaxX, T, 1); 

%Get the unique combinations and an index. Note, I am assuming X is a column vector. 
[UniqueComb, ~, Ind] = unique([X(1:end-1), X(2:end)], 'rows'); 
NumComb = size(UniqueComb, 1); 

%Count the number of occurrences of each combination 
Count = accumarray(Ind, 1); 

:ここ

は、私はそれを解決する方法です。ここで

+0

'Count = accumarray(Ind、1);'はおそらくループでカウントするよりも速いでしょう。また、一意の行の数が正しく機能するように、Xは列ベクトルでなければならないことを示す必要があります。 –

+0

@EitanTありがとうございました。私は答えに 'accumarray'を組み込みました。列ベクトルの問題については、コード内のコメントに「X」が列ベクトルである必要があることを示しました。余分なビットはAmroの幻想的な「疎な」アプローチだが:-) –

関連する問題