7

私はかなり大きな配列を持っています。物事を単純にするために、それを単純化して次のようにします。

A = [1 1 1 1 2 2 3 3 3 3 4 4 5 5 5 5 5 5 5 5];

したがって、1(4要素)、2(2要素)、3(4要素)、4(2要素)、および5(8要素)のグループがあります。ここで、3つ以上の要素のグループに属する列のみを保持したいと思います。したがって、次のようになります。

B = [1 1 1 1 3 3 3 3 5 5 5 5 5 5 5 5];

私はforループを使用して、1、2、3などを別々にスキャンしていましたが、大きな配列では非常に遅くなります...より効率的な方法でそれを行う方法を提案してくれてありがとう:)アート。

4

4 に答える 4

8

一般的なアプローチ

ベクトルが必ずしもソートされていない場合は、ベクトル内の各要素の出現回数をカウントするために実行する必要があります。あなたはhistcそのためだけに持っています:

elem = unique(A);
counts = histc(A, elem);
B = A;
B(ismember(A, elem(counts < 3))) = []

最後の行は、出現回数が3回未満の要素を選択し、それらを削除します。

グループ化されたベクトルのアプローチ

ベクトルが「半ソート」されている場合、つまり、ベクトル内の類似した要素がグループ化されている場合(例のように)、次のようにすることで処理を少し高速化できます。

start_idx = find(diff([0, A]))
counts = diff([start_idx, numel(A) + 1]);
B = A;
B(ismember(A, A(start_idx(counts < 3)))) = []

繰り返しになりますが、ベクトルを完全に並べ替える必要はなく、類似した要素が互いに隣接しているだけであることに注意してください。

于 2012-09-20T11:54:26.730 に答える
7

これが私の2ライナーです

counts = accumarray(A', 1);
B = A(ismember(A, find(counts>=3)));

accumarrayは、Aの個々のメンバーをカウントするために使用されます。findは、「3つ以上の要素」の基準を満たすメンバーを抽出します。最後に、ismemberはそれらがAのどこにあるかを示します。Aをソートする必要はないことに注意してください。もちろん、accumarrayはAの整数値に対してのみ機能します。

于 2012-09-20T12:15:04.973 に答える
3

あなたが説明しているのはランレングスエンコーディングと呼ばれています。

FileExchangeのMatlabにこのためのソフトウェアがあります。または、次のように直接行うことができます。

len = diff([ 0 find(A(1:end-1) ~= A(2:end)) length(A) ]);
val = A(logical([ A(1:end-1) ~= A(2:end) 1 ]));

ランレングスエンコーディングを取得したら、長さに基づいて要素を削除できます。すなわち

idx = (len>=3)
len = len(idx);
val = val(idx);

次に、デコードして必要な配列を取得します。

i = cumsum(len);
j = zeros(1, i(end));
j(i(1:end-1)+1) = 1; 
j(1) = 1; 
B = val(cumsum(j));
于 2012-09-20T11:21:07.197 に答える
1

matlabビルトインを使用してそれを行う別の方法があります。

% Set up
A=[1 1 1 1 2 2 3 3 3 3 4 4 5 5 5 5 5];
threshold=2;

% Get the unique elements of the array
uniqueElements=unique(A);

% Count haw many times each unique element occurs
counts=histc(A,uniqueElements);

% Write which elements should be kept
toKeep=uniqueElements(counts>threshold);

% Make a logical index
indexer=false(size(A));
for i=1:length(toKeep)
    % For every unique element we want to keep select the indices in A that
    % are equal
    indexer=indexer|(toKeep(i)==A);
end

% Apply index
B=A(indexer);
于 2012-09-20T11:28:51.930 に答える