2016-05-01 6 views
2

私はある種の補間アルゴリズムを実装しようとしています。 IはN * 4の行列であり、周囲の点のインデックスをNの他の点で保持します。しかし、各行の要素がIである場合は、一意ではない可能性があります。つまり、2つ以上が個別のポイントを参照する可能性があります。各行でどれだけユニークなインデックスが利用できるかを知りたいのですが、Nが大きいので、できるだけ早くそれをやりたいのです!行列の各行に固有の要素の数を見つける方法は?

答えて

1

まあ、Mohsen's answerはこの問題の一般的な解決策ですが、arrayfunは私にとっては遅すぎました。だから私はそれについてもう少し考え、はるかに速い解決策を見つけました。 私は、列のすべてのペアを比較し、それらが等しかった場合、カウンタを増やす:

tic; 
S = zeros(N, 1, 'uint32'); 
Nu = S+4; % in my case most of point are surrounded by four different points 
for i=1:3 
    for j=(i+1):4 
     S = S + uint32(I(:, i)==I(:, j)); 
    end 
end 
% Nu(S==0) = 4; 
Nu(S==1) = 3; 
Nu((S==2)|(S==3)) = 2; % why? :) 
Nu(S==6) = 1; 
toc; 

N=189225について、arrayfunは私のPC上で14.73sかかりますが、合計は0.04sかかります。

編集:ここでは、上記のコードの変更の列

の異なる数の世話をします。今度は、各行にユニークな値の場所を持つこともできます。これには:)の問題がなく、より多くの列に使用できます。私のPCで189225行の0.04秒をとりました。

tic; 
uniq = true(N, 4); 
for i=1:3 
    for j=(i+1):4 
      uniq(I(:, i)==I(:, j), j) = false; 
    end 
end 
Nu = sum(uniq, 2); 
toc; 

編集(2):私は列の数が異なる行列の各行のユニークな要素の数を望んでいた別の問題のためにこれを必要しばらくEBHanswer

との比較。そこで私のコードとEBHのコードを比較して、コードが高速かどうかを調べました。 3つの異なる実行の(秒)費やした時間の平均Iが6〜60の結果から、両方の10Kから100Kの行を持つマトリックス上のコード、および列を走っている:私はこれをテストしてい

enter image description here

MATLABの最新バージョンではforループのパフォーマンスが大幅に改善されています。古いバージョンで実行したい場合は、自分で比較する必要があるかもしれません。ここで

2

は、各列にunique関数を使用し、結果の要素をカウントする必要があります

arrayfun(@(x) numel(unique(I(x,:))), (1:size(I,1)).') 

結果が列ベクトルになるようにインデックス配列を転置されます。

+0

私の答えを確認してください。 mamnoon misham;) – saastn

+0

一意の要素としてゼロを考慮しないように、上記の構文をどのように編集するのですか? – Sade

+0

'setdiff(I(x、:)、0)に' unique(I(x、:)) 'を変更します。 –

1

はループせずにこれを行うには、超高速な方法です:

accumarray(repmat(1:size(I,1),1,size(I,2)).',I(:),[],@(x) numel(unique(x))) 

これはあなたの場所kの要素がI(k,:)でユニークな要素の数であるベクトルの大きさNを、提供します。

関連する問題