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

5 vues (au cours des 30 derniers jours)
Benjamin Colbert
Benjamin Colbert le 7 Sep 2022
Modifié(e) : Fifteen12 le 13 Sep 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,:) = []

Réponses (2)

David Hill
David Hill le 7 Sep 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 le 7 Sep 2022
Modifié(e) : Fifteen12 le 13 Sep 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 commentaires
Benjamin Colbert
Benjamin Colbert le 12 Sep 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 le 13 Sep 2022
Modifié(e) : Fifteen12 le 13 Sep 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.

Connectez-vous pour commenter.

Catégories

En savoir plus sur Matrices and Arrays dans Help Center et File Exchange

Tags

Community Treasure Hunt

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

Start Hunting!

Translated by