如何用matlab编程实现多重过滤

题目描述

matlab编程小白一枚 请求各位大神给个思路 用matlab编程造一个过滤器过滤数据里的条目

题目来源及自己的思路

手头上有一份原始数据 没有标签只有数字那种 其中的第二列是心跳
现在需要把心跳检测为0的条目过滤掉

之前都是撸的别的语言 完全没思路。。。
老板给的思路是提取increment

相关代码

// 请把代码文本粘贴到下方(请勿用图片代替代码)
部分数据:(没有标签 没有标签 只有数字 第二列是心跳)
0.00 0 -1 -1 -127 -1 -1 52 -1
0.25 0 -1 -1 -127 -1 -1 52 -1
0.50 0 -1 -1 -127 -1 -1 51 -1
0.75 0 -1 -1 -127 -1 -1 51 -1
1.00 0 -1 -1 -127 -1 -1 50 -1
1.25 0 -1 -1 -127 -1 -1 50 -1
1.50 0 -1 -1 -127 -1 -1 50 -1
1.75 0 -1 -1 -127 -1 -1 52 -1
2.00 0 -1 -1 -127 -1 -1 52 -1
2.25 0 -1 -1 -127 -1 -1 54 -1
2.50 0 -1 -1 -127 -1 -1 53 -1
2.75 133 -1 -1 -127 -1 -1 54 -1
3.00 133 -1 -1 -127 -1 -1 56 -1
3.25 130 -1 -1 -127 -1 -1 54 -1
3.50 130 -1 -1 -127 -1 -1 56 -1
3.75 126 -1 -1 -127 -1 -1 57 -1
4.00 126 -1 -1 -127 -1 -1 56 -1
4.25 121 -1 -1 -127 -1 -1 56 -1
4.50 121 -1 -1 -127 -1 -1 56 -1
4.75 120 -1 -1 -127 -1 -1 52 -1

你期待的结果是什么?实际看到的错误信息又是什么?

过滤条件:
1.检测到一条数据心跳为0时, 如果从这条开始计算,后续累计的0的条目数小于等于20, 批量删除掉这些条目;
2.如果后续累计的0的条目大于20小于80, 计算平均数:(起始0条目之前的非0条目+累计0条目结束后第一条非0条目)/2
然后把算出的平均数安到这些条目里去

有点复杂 求一个思路和相关命令关键词 跪谢

阅读 2.7k
2 个回答

如果你的数据库是M,即

M = [
0.00 0 -1 -1 -127 -1 -1 52 -1
0.25 0 -1 -1 -127 -1 -1 52 -1
0.50 0 -1 -1 -127 -1 -1 51 -1
0.75 0 -1 -1 -127 -1 -1 51 -1
....
4.50 121 -1 -1 -127 -1 -1 56 -1
4.75 120 -1 -1 -127 -1 -1 52 -1
];

最直接的思路是用一个简单粗暴的for循环:


MSub = M(:,2); % 先把第二列提出来,提高检索效率
skipCountCache = 0; % 数据为0,连续跳过计数暂存
finalSkipCount = 0; % 最终需要略去的数据计数
accumsum = 0; %累和
for i = 1:numel(MSub)
    if M(i) == 0
        skipCountCache = skipCountCache + 1;
        if skipCountCache > 80 % 若跳过计数超过80,退出循环计算平均数
            break;
        end
        continue;
    end

    if skipCountCache > 20
        skipCountCache = 0; % 若跳过计数超过20,重置计数
    else                
        finalSkipCount = finalSkipCount + skipCountCache; % 否则计入finalSkipCount
        skipCountCache = 0; % 重置计数
    end
            
    accumsum = accumsum + MSub(i);
end

finalSkipCount = finalSkipCount + skipCountCache; 把最后所有的0都计入finalSkipCount
average = accumsum / (i - finalSkipCount);

for循环很好理解,也很好写,但是运行效率不高,特别是当你的数据量较大时。

这时候,我们可以用另一种方法,创建一个0和1组成的过滤器(实质上是一个logical array),然后用finddiff对过滤器处理。

MSub = M(:,2);
zeroFilter = MSub == 0; % 过滤器
boundaryFinder = diff(zeroFilter); % 查找过滤器边界;边界即从0到1和从1到0
openingZeroIndices = find(boundaryFinder == 1); % 从0到非0的数据index-1
closingZeroIndices = find(boundaryFinder == -1); % 从非0到0的数据index
endWithZero = false; 
if MSub(1) == 0 % 若数据是以0开始
    openingZeroIndices = [0; openingZeroIndices];
end
if MSub(end) == 0 % 若数据是以0结尾
    endWithZero = true;
    closingZeroIndices = [closingZeroIndices; numel(MSub)];
end

assert(numel(openingZeroIndices) == numel(closingZeroIndices)); % 确保每一个openingZero都对应一个closingZero

zeroGroupSizes = closingZeroIndices - openingZeroIndices;  % 每一组连续0的数量
assert(all(zeroGroupSizes>0)); % 确保数字都大于0

terminateIndex = openingZeroIndices(zeroGroupSizes >= 80); % 如果有连续0的数量大于等于80的,在这组数据之前终止求和。

if isempty(terminateIndex) % 若连续0的数量都小于80,在最后一个非零数据终止求和。
    if endWithZero
        terminateIndex = openingZeroIndices(end);
    else
        terminateIndex = numel(MSub);
    end
end

finalSkipCount = sum(zeroGroupSizes(zeroGroupSizes <= 20)); % 最终需要略去的数据计数
average = sum(MSub(1:terminateIndex)) / (terminateIndex - finalSkipCount); % 求平均数


这真的是超出预期了 跪谢大神!

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进