Delete row based on criteria of 2 variables

5 visualizzazioni (ultimi 30 giorni)
BenL
BenL il 13 Gen 2017
Commentato: Adam il 14 Gen 2017
In matrix A, I have n X 6 columns. In matrix B, I have n X 1 column. What I want to do is, if the element in column 6 of matrix A is larger than the element in column 1 of matrix B (i.e. A(:,6) > B(:,1)), then delete the row. Both matrices are of type double. What is the best way to script this?
I tried this:
for i = 1:n
if A(i, 6) > B(i, 1);
A(i,:) = [];
end
end
But it was quite slow (i have approx. 400,000 x 30 rows of data). Any other ways?
  3 Commenti
Adam
Adam il 13 Gen 2017
I would also expect this to do highly unwanted things. You should never delete elements from an array that you are looping round in a for loop because the indices will change so I would have expected this to crash with an index exceeds matrix dimensions at some point because your matrix is shrinking below n rows (unless you delete nothing) so when you get to the iteration of the for loop greater than the new size of your array it will crash with
Index exceeds matrix dimensions.
If you must delete things in a loop (in general programming, not here where the solutions below are far better) then always do it with a reverse iteration from back to front.
Roger Stafford
Roger Stafford il 13 Gen 2017
Modificato: Roger Stafford il 13 Gen 2017
@BenL. As Adam has pointed out, your for-loop method will “do highly unwanted things.” Among these things is the fact that after a row has been deleted, since you do not delete the same row in matrix B, thereafter comparison of matching rows in A and B will be erroneous because the rows that previously had equal indices no longer do. Moreover, by erasing one row, if the next row was also to have been erased, that second row deletion will be skipped, because with its row position in A having been reduced by one, the for-loop would have to repeat its previous value i index value to accomplish the deletion, which of course it will not do. As Adam has pointed out, deleting elements in a vector one-at-a-time in a for-loop with increasing index value is a dangerous thing to do.

Accedi per commentare.

Risposta accettata

Adam
Adam il 13 Gen 2017
A( A(:,6) > B, : ) = [];
  2 Commenti
BenL
BenL il 14 Gen 2017
This works so fast! I wonder what makes it so different?
Adam
Adam il 14 Gen 2017
Vectorisation and indeing operations are what Matlab is good at and optimised for. For loops are not as bad as they are sometimes made out to be and have been in the past, but they are still nowhere near as fast as vectorisation in most (or all) cases.

Accedi per commentare.

Più risposte (1)

Star Strider
Star Strider il 13 Gen 2017
See if this does what you want:
N = 10;
A = randi(9, N, 6); % Create Data
B = randi(9, N, 1); % Create Data
Q = A; % Copy For Reference
A(A(:,6) > B,:) = []; % Desired Result

Categorie

Scopri di più su Creating and Concatenating Matrices in Help Center e File Exchange

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!

Translated by