MATLAB多列find索引提取:解决列长度不一致的高效实现方案
场景设定
我有一组捕获数据的数组,数据来自1到12台设备,每台设备对应数组中的一列。已将数组转换为逻辑数组以定位数据中的特定关注点,数组中包含大量0,仅少数1。我需要返回一个包含1的索引的数组,用于后续提取这些索引之间的数据(见下方更新)。
find是首选函数,但我需要的是每列对应一台设备的索引数组,而默认情况下find会返回线性索引,与数组维度无关。
各设备的数据遵循相似模式但并非完全一致,由于数据捕获停止时机不同,每列中1的数量相近但不保证完全相同(通常相差1个元素,也可能相差更多)。
MATLAB代码尝试
由于列长度不一致,无法使用以下简单代码:
for p = 1:np indices( :, p ) = find( device.data.cross( :, p ) ); end
说明:
np为数据列数,即捕获的设备数量。devices是表示设备集合的class。data是包含所有设备捕获数据的TimeTable。cross是dataTimeTable中的一列,存储逻辑数组。- 这段代码不仅效率低下,还会触发代码分析器警告:
变量'indices'在每次循环迭代中似乎都会改变大小(在脚本中)。考虑预分配以提高速度。
正如预期,这段代码无法运行,会出现类似如下错误:
无法执行赋值,因为左侧的大小为448×1,右侧的大小为449×1。
我清楚错误原因:MATLAB数组的每列必须具有相同行数,因此行大小不匹配时无法完成赋值。我需要对"较短"的列进行填充,在此场景下,重复最后一个索引即可满足后续操作需求且不会报错。
但执行find操作前无法确定行数,无法预先分配数组,于是我将代码修改为如下形式:
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
这只是我对"数据块"执行的其中一个操作,我还有几个函数需要传入这些数据块进行处理。
内容的提问来源于stack exchange,提问作者Trashman

