如何在matlab中根据满足的条件删除一组行?有代码,但不确定出了什么问题?

k5ifujac  于 2022-11-15  发布在  Matlab
关注(0)|答案(1)|浏览(266)

我正在尝试检测高振幅事件,并将它们与上下几行一起移除。我有下面的代码,它部分地实现了这一点,但不是完全的,我不确定错误在哪里。我已经注解掉了Audioread功能,并添加了Randi以允许重现结果。代码:

%[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
vxbzzdmp

vxbzzdmp1#

我认为您的代码的主要问题是在循环data时修改它。这意味着,您删除了索引大于i的行中的峰值(或您的话中的高幅度事件),以便在后续迭代中不会考虑它们。
例如,考虑索引为46的行中的峰值,这应该会导致移除直到索引16的行(其值为clear_range equal10)。但是,当i等于4时,将删除索引14以下的行。因此,您还删除了位置6处的峰值,以便在以后的迭代中不会将其考虑在内。
一般而言,依赖于MatLab的矩阵/数组运算比使用循环更容易。请在下面找到一个可能的解决方案,并在线解释。

clc;
% I adjusted inputs to get a minimal example
data            = randi(10,30,1);
threshold       = 9; 
rangeToClear    = 1;
columnToCompare = 1;

dataOut         = clearRange(data, threshold, rangeToClear, columnToCompare );

disp('In:')
disp( data' ); 

disp('Out:')
disp( dataOut' ); % Plot for cross-check

function data = clearRange(data, threshold, rangeToClear, columnToCompare)

% rowsWithPeak is 1-D logical array showing where columnToCompare is greater than the threshold 
rowsWithPeak = data( :, columnToCompare ) > threshold;

% kernel is a column vector of ones of size Nx1, where N is the number of rows 
% that should be removed around a peak
kernel = ones( 2*rangeToClear+1, 1 );

% rowsToRemove is a column vector being greater than one at row indices
% that should be removed from the data. To obtain rowsToRemove, 
% we convolute rowsWithPeak with the kernel. The argument 'same' to 
% the conv2 function, specifies that rowsToRemove will have the same
% size as rowsWithPeak.
rowsToRemove = conv2( rowsWithPeak, kernel, 'same' );

% rowsToRemoveLogical is a logical array being one, where rowsToRemove is greater than 0.
% Note that, rowsToRemoveLogical = rowsToRemove > 0 would also work here
rowsToRemoveLogical = logical( rowsToRemove);

% Finally, we use rowsToRemoveLogical to mask positions of the rows that should be removed.
data( rowsToRemoveLogical, : ) = [];

end

相关问题