10

マトリックスからいくつかの特定の値を削除したい (存在する場合)。マトリックス内に複数の値のコピーが存在する可能性が非常に高くなります。

たとえば、N 行 2 列の行列について考えてみintersectionsます。値のペアと[a b]その[c d]マトリックスの行として存在する場合、それらを削除したいと思います。

次のマトリックスのような行を削除したいとしましょう[-2.0 0.5][7 7]

intersections =

   -4.0000    0.5000
   -2.0000    0.5000
    2.0000    3.0000
    4.0000    0.5000
   -2.0000    0.5000

そのため、削除後に次のようになります。

intersections = 

   -4.0000    0.5000
    2.0000    3.0000
    4.0000    0.5000

これを行う最も効率的/エレガントな方法は何ですか?

4

4 に答える 4

13

このワンライナーを試してください ( Aは交点行列、Bは削除する値です)。

A = [-4.0 0.5;
     -2.0 0.5;
      2.0 3.0;
      4.0 0.5;
     -2.0 0.5];
B = [-2.0 0.5];
A = A(~all(A == repmat(B,size(A,1),1),2),:);

次に、削除する新しいBごとに最後の行を繰り返します。

編集:

...そしてここに別のオプションがあります:

A = A((A(:,1) ~= B(1)) | (A(:,2) ~= B(2)),:);

警告:ここでの回答は、小さな浮動小数点エラーが予想されない場合 (つまり、整数値の場合) に最適です。このフォローアップの質問に記載されているように、「==」および「~=」演算子を使用すると、望ましくない結果が生じる可能性があります。このような場合、等値演算子の代わりに関係演算子を使用するように上記のオプションを変更する必要があります。たとえば、追加した 2 番目のオプションは次のように変更されます。

tolerance = 0.001;   % Or whatever limit you want to set
A = A((abs(A(:,1)-B(1)) > tolerance) | (abs(A(:,2)-B(2)) > tolerance),:);

ちょっと頭を上げてください!=)


基本的なタイミング:

誰かが本当に効率に興味がある場合に備えて、マトリックスのサブインデックスを取得する 3 つの異なる方法 (上記の 2 つのオプションとFanfan のSTRMATCH オプション)について簡単なタイミングを計りました。

>> % Timing for option #1 indexing:
>> tic; for i=1:10000, index = ~all(A == repmat(B,size(A,1),1),2); end; toc;
Elapsed time is 0.262648 seconds.
>> % Timing for option #2 indexing:
>> tic; for i=1:10000, index = (A(:,1) ~= B(1)) | (A(:,2) ~= B(2)); end; toc;
Elapsed time is 0.100858 seconds.
>> % Timing for STRMATCH indexing:
>> tic; for i=1:10000, index = strmatch(B,A); end; toc;
Elapsed time is 0.192306 seconds.

ご覧のとおり、STRMATCH オプションは最初の提案よりも高速ですが、2 番目の提案は 3 つすべての中で最速です。ただし、私のオプションと Fanfan のオプションは少し異なることを行うことに注意してください。私のオプションは行の論理インデックスを返し、Fanfan は削除する行の線形インデックスを返します。そのため、STRMATCH オプションは次の形式を使用します。

A(index,:) = [];

私がフォームを使用している間:

A = A(index,:);

ただし、最初の形式を使用するためにインデックスを無効にすることができます (削除する行のインデックス):

A(all(A == repmat(B,size(A,1),1),2),:) = [];    % For option #1
A((A(:,1) == B(1)) & (A(:,2) == B(2)),:) = [];  % For option #2
于 2009-03-25T22:28:34.390 に答える
5

必要に応じて strmatch 関数を悪用することもできます。次のコードは、行列 A 内の特定の行 b の出現をすべて削除します。

A(strmatch(b, A),:) = [];

マトリックス B のすべての行など、複数の行を削除する必要がある場合は、それらを反復処理します。

for b = B'
   A(strmatch(b, A),:) = [];
end
于 2009-03-25T23:56:00.577 に答える
0

この機能がいつ導入されたのか (2​​012b を使用) はわかりませんが、次のことができます。

setdiff(A, B, 'rows')
ans =

   -4.0000    0.5000
    2.0000    3.0000
    4.0000    0.5000

に基づく:

A = [-4.0 0.5;
     -2.0 0.5;
      2.0 3.0;
      4.0 0.5;
     -2.0 0.5];
B = [-2.0 0.5];
于 2013-10-31T14:17:04.770 に答える