How do I delete a group of rows when a condition is met in one?

4 visualizaciones (últimos 30 días)
Benjamin Colbert
Benjamin Colbert el 7 de Sept. de 2022
Editada: Fifteen12 el 13 de Sept. de 2022
Let's say I have a matrix which is 1000x1. When the value of a row > 0.25, I want to delete that row and 10 rows above and below. (e.g., of value of row 30 = 0.5, rwos 20-40 would be deleted). I have the follwoing starting point but not sure how to select the rows above and below.
data(data > 0.25,:) = []

Respuestas (2)

David Hill
David Hill el 7 de Sept. de 2022
f=find(data>.25);
idx=[];
for k=1:length(f)
idx=[idx,(f(k)-10):(f(k)+10)];
end
idx=unique(idx);
idx=idx(idx>0&idx<=length(data));
data(idx)=[];

Fifteen12
Fifteen12 el 7 de Sept. de 2022
Editada: Fifteen12 el 13 de Sept. de 2022
Simple but long answer using an iterator:
Edits: Changed code to catch moving indices as data is resized and expand removal range if trigger values are found in the initial set.
data1 = randi(10,10,1);
threshold = 7;
clear_range = 2; %rows/samples
data = clearRange(data1, threshold, clear_range);
function [data] = clearRange(data, threshold, clear_range, compare_column)
% data: matrix of values to clean
% threshold: delete values greater than threshold
% clear_range: number of rows to delete
% compare_column: column to check for value to compare against threshold
if nargin < 4
compare_column = 1;
end
i = 1;
while i <= length(data)
if data(i,compare_column) > threshold
to_delete = [max(1, i-clear_range), min(length(data), i+clear_range)];
j = i + 1;
while j <= to_delete(2)
if data(j, compare_column) > threshold
to_delete = [to_delete(1), min(j + clear_range, length(data))];
end
j = j + 1;
end
data(to_delete(1):to_delete(2), :) = [];
i = max(1, i - clear_range);
else
i = i + 1;
end
end
end
  3 comentarios
Benjamin Colbert
Benjamin Colbert el 12 de Sept. de 2022
Here's a reproducable example, You can see it does not remove all values above the threshhold.
%[data, fs] = audioread("noise.wav");
%t1 = linspace(0, (numel(data)-1)/fs, numel(data));
rng(1)
data = randi(10,1000,1);
threshold = 5;
clear_range = 10; %rows/samples
data = clearRange(data, threshold, clear_range);
%t1 = linspace(0, (numel(data)-1)/fs, numel(data));
%plot(t1, data);
plot(data)
function [data] = clearRange(data, threshold, clear_range, compare_column)
% data: matrix of values to clean
% threshold: value to compare values against
% clear_range: number of rows to delete
% compare_column: column to check for value to compare against threshold
if nargin < 4
compare_column = 1;
end
for i = 1:length(data)
if i > length(data)
break
end
if data(i,compare_column) > threshold
data(max(1, i-clear_range):min(length(data), i+clear_range),:) = [];
end
end
end
Fifteen12
Fifteen12 el 13 de Sept. de 2022
Editada: Fifteen12 el 13 de Sept. de 2022
Good catch. The problem was that the data matrix was being shifted every time a range was cleared, so the for loop was essentially jumping "clear_range" rows every time it was called.
There was an additional item of consideration where values over the threshold that are within the clearing range of another value are deleted before they can be considered by the algorithm. I've also edited the code to check each value before it's deleted, and extend the clearing range if a trigger value is found.
The code is pretty unoptimized, again, simple but slow in this case. You'd get much better performance by vectorizing. @David Hill's solution works fine and solves both of these problems with much better performance. I can't think of any reason to utilize mine versus his.

Iniciar sesión para comentar.

Categorías

Más información sobre Matrices and Arrays en Help Center y File Exchange.

Etiquetas

Community Treasure Hunt

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

Start Hunting!

Translated by