如果对你有帮助记得素质三连~
转载请注明出处~
https://blog.csdn.net/L_Open2021/article/details/123249099
1.需求
有一组使用物理设备采集的数据,使用之前需要进行数据平滑,过滤掉正向数据中的反向波动数据和反向数据中的正向波动数据以及错误数据
2.问题
我们只能拿到这组数据,但是无法确认方向(如果可以确认方向的话可以直接通过方向判断错误值了,不需要这么麻烦),所以写了此方法
3.方案
我们取了固定数量的前几组数据作为判断方向的依据,此方案只能优化不能根治(当方向变了的时候那里,会有概率出现波动的情况)
我直接将数据存储到了内存中,可以结合实际业务存储到如redis中
4.代码
import java.util.*;
import java.util.stream.Collectors;
/**
* 平滑取值 防抖
*/
public class Test2 {
public static void main(String[] args) {
//模拟数据从5.9开始方向执行
List<Double> list = Arrays.asList(
1.0, 1.1, 1.2, 1.4, 2.0, 2.1, 8.0, 3.0, 2.2, 3.1, 3.2, 2.1, 2.0, 4.0, 5.0, 6.0,
5.9, 5.8, 5.2, 5.3, 5.0, 4.9, 4.8, 4.7, 4.6, 4.5, 4.6, 4.4, 4.2, 4.0, 3.0, 3.1, 3.2, 3.8, 0.2, 2.9, 2.5, 8.0, 8.0, 0.1, 1.0
);
judge(list);
}
//实际业务中我是将这两个数据存放在了redis中
//存放所有数据用于判断方向,不包含大波动数据,我这里为了方便计算就存了九个(数量为单数最佳)
private static List<Double> allDataList = new ArrayList<>();
//存放所有上次推送的数据,使用只使用最后一次推送的数据,所以也可以改成double类型
private static List<Double> pushDataList = new ArrayList<>();
private static void judge(List<Double> list) {
for (Double newValue : list) {
Double oldValue = 0D;//上次推送的数值
Double differenceValue = 0D;//本次值和上次推送的差值
Double ignoreValue = 2D;//根据差值计算比对后需要直接忽略的值,大波动值
Double differenceAmount = 9D;//差值数量,控制allDataList的存储数量及计算精度,此数值越大越好,根据实际业务数据数量而定
//抖动绝对值超过2则直接跳出循环,不往数组中新增数据
if (!allDataList.isEmpty()) {
//获取上一次推送的数据,之前无推送则从所有数据中上次的数据
oldValue = !pushDataList.isEmpty() ? pushDataList.get(pushDataList.size() - 1) : allDataList.get(allDataList.size() - 1);
differenceValue = newValue - oldValue;
if (differenceValue > ignoreValue || differenceValue < -ignoreValue) {
continue;
}
}
//这里做数量处理,多余的去掉
if (allDataList.size() > differenceAmount) {
allDataList.remove(0);
}
allDataList.add(newValue);
int allRedisDateListSize = allDataList.size();
if (allRedisDateListSize > differenceAmount) {
List<Integer> directionList = new ArrayList<>();//存方向数组,用于判断最终方向
//这里计算之前所有数据中的差值正负,1 -1 0
for (int i = 0; i < allRedisDateListSize; i++) {
Double d1 = allDataList.get(i);
Double d2;
//没有下一个值了直接结束循环
try {
d2 = allDataList.get(i + 1);
} catch (IndexOutOfBoundsException e) {
break;
}
// 下面代码的解释: Integer direction = d2-d1==0D?0:d2-d1>0D?1:-1;
Integer direction = Double.compare(d2 - d1, 0D);
directionList.add(direction);
}
List<Integer> plusList = directionList.stream().filter(r -> r > 0).collect(Collectors.toList());//筛选数据大于0的列表,
List<Integer> minusList = directionList.stream().filter(r -> r < 0).collect(Collectors.toList());//筛选数据小于0的列表
//通过directionList判断正负方向,这里判断就写的多点,方便扩展
if (!plusList.isEmpty() && plusList.size() > directionList.size() / 2) {//正方向
//如果新数值是负方向,则说明新数值错误,需推送上一次推送的数据
if (differenceValue < 0) {
System.out.print(oldValue + " / ");
pushDataList.add(oldValue);
continue;
}
} else if (!minusList.isEmpty() && minusList.size() > directionList.size() / 2) {//负方向
//如果新数值是正方向,则说明新数值错误,需推送上一次推送的数据
if (differenceValue > 0) {
System.out.print(oldValue + " / ");
pushDataList.add(oldValue);
continue;
}
} else if (!plusList.isEmpty() && plusList.size() == minusList.size()) {//不正不负
//目前数据没方向,直接推送上次数据
System.out.print(oldValue + " / ");
pushDataList.add(oldValue);
}
//不符合上面所有条件的话,推送最新的数据
System.out.print(newValue + " / ");
pushDataList.add(newValue);
}
}
}
}
5.输出结果
版权归原作者 孤卷者 所有, 如有侵权,请联系我们删除。