MatLab在多列上查找多列结果

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

设置

我有一组捕获的数据。数据可以只在一个设备上捕获,也可以在多达十几个设备上捕获,每个设备都是阵列中的一列。我有一个先前的语句,我在数组上执行该语句,然后将其转换为逻辑数组,以便在数据中找到特定的兴趣点。由于数据的性质,有很多0,只有几个1。我需要返回一个带有1的索引的数组,这样我就可以返回并捕获*这些点之间的数据(参见下面的更新)。
find显然是函数的选择--然而,我需要的结果是,每个设备需要有1列。通常,find将执行线性索引,而与数组的维度无关。
这些设备遵循一个模式--但并不完全相同。因此,使情况更复杂的是,根据数据捕获停止的确切时间,每列中的1的数量接近,但不能保证完全相同(它们通常彼此相差1个元素,但可能相差更多)。

MatLab代码尝试

由于这种差异,我不能使用以下简单的代码:

for p = 1:np
    indices( :, p ) = find( device.data.cross( :, p ) );
end

备注:

  • np是数据中的列数=捕获的设备数。
  • devices是代表设备集合的class
  • data是包含在所有设备上捕获的数据的TimeTable
  • cross是包含逻辑阵列的dataTimeTable中的一列
  • 即使是这个简单的代码效率也很低,并生成代码分析器警告:

变量‘index’似乎在每次循环迭代时改变大小(在脚本中)。考虑为速度进行预分配。
正如预期的那样,它无法工作,因为我收到了类似以下内容的错误:
无法执行赋值,因为左侧的大小为448 x 1,右侧的大小为449 x 1。
我知道为什么会出现这个错误--在MATLAB中,数组中的每一列都必须有相同的行数,所以如果行大小不匹配,我就不能进行赋值。我需要以某种方式填充“短”栏。在这种情况下,重复最后一个索引将对我以后的操作起作用,而不会导致错误。
我想不出一个“好”的办法来做这件事。我不能预填充数组行,因为在完成查找操作之前,我不知道将有多少行。
我可以按如下方式更改代码:

indices = [];
    for p = 1:np
        tempindices = find( devices.data.cross(:, p) );
        sizediff = size( tempindices, 1 ) - size( indices, 1 );
        
        if p > 1
            
            if sizediff > 0

                padding = repmat(indices(end, 1:(p - 1)), sizediff, 1);
                indices = [indices; padding];

            elseif sizediff < 0

                padding = repmat(tempindices(end), abs(sizediff), 1);
                tempindices = [tempindices; padding];

            end
            
        end

        indices(:,p) = tempindices;
        
    end

注意:padarray在这里会很有用,但我没有Image Processing Toolbox,所以我不能使用它。
这段代码可以工作,但效率非常低,它在工作区中创建了多个原本不需要的变量,并在代码分析器中生成了多个“似乎在每次循环迭代中更改大小”的警告。有没有更有效的方法来做到这一点?

更新/补充信息:

我的问题需要一些更多的背景。鉴于devices.data.cross是一个逻辑数组,为了从表中的其他列“挑选”我想要的数据(正如我最初描述的问题),我可以从devices.data.cross中选择一列,并将该逻辑列作为下标传递以获得该数据。我在管用的地方就会这么做。然而,对于某些列,我需要选择索引之间的“块”数据,这就是我需要索引的地方。或者,至少我不知道另一种方法。
下面是我如何使用索引的示例代码:

for p = 1:np
    for i = 2:num_indices

        these_indices = indices(i-1, p):( indices(i, p) - 1 );
        rmsvoltage = sqrt( mean( devices.data.voltage(these_indices).^2 ) );

    end

end

这只是我对“大块”数据所做的一个例程。我还有几个传递这些数据块以进行处理的函数。

wz8daaqr

wz8daaqr1#

当我正确理解您的问题时,下面的代码应该可以工作。我正在使用克里斯·卢恩戈在你问题下的评论中建议的方法。
关键元素是[rowIdcs, colIdcs] = find( cros );,它给出了cros中值为1的位置的下标。请在内联中找到更多评论。

% Create some data for testing
volt = randn(10,10);
cros = randi(10,10,10) > 9;

% Get rowIdcs and colIdcs, which have both a size of Nx1, 
% with N denoting the number of ones in the mask.
% rowIdcs and colIdcs are the subscripts of the ones in the mask.
[rowIdcs, colIdcs] = find( cros );

% The number of chunks is equal to number N of ones found in the mask;
numChunks = numel( rowIdcs ); 

% Initilize a vector for the rms
rms = zeros( numChunks, 1 );

% Loop over the chunks
for k = 1 : numChunks
   
    curRow = rowIdcs(k);
    curCol = colIdcs(k);
    
    % Get indices of range over neighbouring rows
    chunkRowIdcs = curRow + [-1 0 1]; %i.e. these_indices in your example
    
    % Remove indices that are out of range
    chunkRowIdcs( chunkRowIdcs < 1 | chunkRowIdcs > size(volt,1) ) = [];
    
    % Get voltages covered by chunk 
    chunkVoltages = volt( chunkRowIdcs, curCol );
    
    % Get RMS over voltages
    rms(k) = sqrt( mean( chunkVoltages(:).^2 ));
    
end

相关问题