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

3 ビュー (過去 30 日間)
Benjamin Colbert
Benjamin Colbert 2022 年 9 月 7 日
編集済み: Fifteen12 2022 年 9 月 13 日
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,:) = []

回答 (2 件)

David Hill
David Hill 2022 年 9 月 7 日
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 2022 年 9 月 7 日
編集済み: Fifteen12 2022 年 9 月 13 日
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 件のコメント
Benjamin Colbert
Benjamin Colbert 2022 年 9 月 12 日
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 2022 年 9 月 13 日
編集済み: Fifteen12 2022 年 9 月 13 日
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.

サインインしてコメントする。

カテゴリ

Help Center および File ExchangeMatrices and Arrays についてさらに検索

タグ

Community Treasure Hunt

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

Start Hunting!

Translated by