当前位置: 首页 > news >正文

Java滤波去除异常峰值方法(二)

1. 基于滑动窗口的中值绝对偏差(MAD)方法

public static double[] removeContinuousOutliersMAD(double[] data, int windowSize, double threshold) {double[] filtered = Arrays.copyOf(data, data.length);for (int i = 0; i < data.length; i++) {// 计算窗口内的中位数List<Double> window = new ArrayList<>();for (int j = Math.max(0, i - windowSize/2); j <= Math.min(data.length - 1, i + windowSize/2); j++) {window.add(data[j]);}double median = getMedian(window);// 计算MAD (Median Absolute Deviation)List<Double> deviations = new ArrayList<>();for (Double value : window) {deviations.add(Math.abs(value - median));}double mad = getMedian(deviations);// 替换异常值if (mad != 0 && Math.abs(data[i] - median) > threshold * mad) {filtered[i] = median; // 或用邻域值替换}}return filtered;
}private static double getMedian(List<Double> list) {Collections.sort(list);return list.get(list.size() / 2);
}

2、基于连续异常值计数的剔除方法

public static double[] removeContinuousOutliers(double[] data, double threshold, int maxConsecutive) {double[] filtered = Arrays.copyOf(data, data.length);double mean = calculateMean(data);double stdDev = calculateStdDev(data, mean);int consecutiveCount = 0;for (int i = 0; i < data.length; i++) {if (Math.abs(data[i] - mean) > threshold * stdDev) {consecutiveCount++;if (consecutiveCount > maxConsecutive) {// 使用前后非异常值的平均值替换double replacement = findReplacementValue(data, i);filtered[i] = replacement;}} else {consecutiveCount = 0;}}return filtered;
}private static double findReplacementValue(double[] data, int index) {// 向前找第一个非异常值double prev = 0;for (int i = index - 1; i >= 0; i--) {if (Math.abs(data[i] - calculateMean(data)) <= calculateStdDev(data, calculateMean(data))) {prev = data[i];break;}}// 向后找第一个非异常值double next = 0;for (int i = index + 1; i < data.length; i++) {if (Math.abs(data[i] - calculateMean(data)) <= calculateStdDev(data, calculateMean(data))) {next = data[i];break;}}return (prev + next) / 2.0;
}

3. 使用指数加权移动平均(EWMA)检测连续异常

public static double[] detectContinuousAnomaliesEWMA(double[] data, double lambda, double threshold) {double[] filtered = Arrays.copyOf(data, data.length);double ewma = data[0];int anomalyStreak = 0;for (int i = 1; i < data.length; i++) {ewma = lambda * data[i] + (1 - lambda) * ewma;double residual = Math.abs(data[i] - ewma);if (residual > threshold) {anomalyStreak++;if (anomalyStreak >= 3) { // 连续3个点异常// 使用EWMA值替换filtered[i] = ewma;}} else {anomalyStreak = 0;}}return filtered;
}

4. 基于变化率的连续异常检测

public static double[] removeContinuousSpikes(double[] data, double rateThreshold) {double[] filtered = Arrays.copyOf(data, data.length);double[] rates = new double[data.length - 1];// 计算变化率for (int i = 0; i < rates.length; i++) {rates[i] = Math.abs(data[i+1] - data[i]);}// 计算变化率的统计量double rateMean = calculateMean(rates);double rateStd = calculateStdDev(rates, rateMean);// 检测连续异常变化int spikeLength = 0;for (int i = 1; i < data.length - 1; i++) {double prevRate = Math.abs(data[i] - data[i-1]);double nextRate = Math.abs(data[i+1] - data[i]);if ((prevRate > rateMean + rateThreshold * rateStd) && (nextRate > rateMean + rateThreshold * rateStd)) {spikeLength++;if (spikeLength >= 2) { // 连续两个点变化率过大// 使用前后点的平均值替换filtered[i] = (data[i-1] + data[i+1]) / 2.0;}} else {spikeLength = 0;}}return filtered;
}

辅助方法

private static double calculateMean(double[] data) {double sum = 0;for (double d : data) sum += d;return sum / data.length;
}private static double calculateStdDev(double[] data, double mean) {double variance = 0;for (double d : data) variance += Math.pow(d - mean, 2);return Math.sqrt(variance / data.length);
}

测试:

public static void main(String[] args) {double[] data = {10, 10.1, 10.2, 50, 55, 52, 10.3, 10.2, 10.1, 60, 65, 10};// 方法1: 基于MADdouble[] result1 = removeContinuousOutliersMAD(data, 5, 3.0);// 方法2: 基于连续计数double[] result2 = removeContinuousOutliers(data, 2.5, 2);// 方法3: EWMA方法double[] result3 = detectContinuousAnomaliesEWMA(data, 0.2, 3.0);System.out.println("原始数据: " + Arrays.toString(data));System.out.println("MAD方法: " + Arrays.toString(result1));System.out.println("连续计数方法: " + Arrays.toString(result2));System.out.println("EWMA方法: " + Arrays.toString(result3));
}

方法选择建议

  1. MAD方法:对非正态分布数据更鲁棒,适合数据分布未知的情况

  2. 连续计数方法:适合已知异常值最大连续长度的情况

  3. EWMA方法:适合时间序列数据,对缓慢变化的异常更敏感

  4. 变化率方法:适合检测数据中突然的连续跳跃

对于特别长的连续异常,可能需要结合领域知识或更复杂的算法,如基于机器学习的方法。

http://www.dtcms.com/a/310119.html

相关文章:

  • CGA匹兹堡睡眠质量指数量表评估睡眠状况​
  • nCode 疲劳分析场景复杂,企业如何科学合理分配授权资源?
  • Shader开发(六)什么是着色器
  • Go语言常用的设计模式
  • leetcode热题——全排列
  • 视频质量检测中卡顿识别准确率↑32%:陌讯多模态评估框架实战解析
  • 音频获取长度
  • anaconda、conda、pip、pytorch、torch、tensorflow到底是什么?它们之间有何联系与区别?
  • 目标检测检出率,误检率,ap,map等评估python代码
  • SOLIDWORKS教育版
  • 地震光与鸟类异常行为的科学关联性及地震预测潜力评估
  • (AC)五子棋
  • 在 uni-app 中进行路由跳转前的权限验证(检查用户是否登录)
  • OCC任务新SOTA!华科提出SDGOCC:语义深度双引导的3D占用预测框架(CVPR 2025)
  • 基于Pipeline架构的光存储读取程序 Qt版本
  • ansible简单playbook剧本例子3-安装nginx
  • Typora v1.10.8 好用的 Markdown 编辑器
  • 【2】专业自定义图表创建及应用方法
  • flutter release调试插件
  • 通过pendingIntent启动activity被block问题
  • C语言数据结构(3)单链表专题1.单链表概述
  • NDBmysql-cluster融合脚本
  • (二)LoRA微调BERT:为何在单分类任务中表现优异,而在多分类任务中效果不佳?
  • Spring Boot微服务性能优化实践指南:从配置到监控
  • SpringCloud(一)微服务基础认识
  • 什么是三防平板电脑?三防平板有什么作用?
  • 浏览器【详解】自定义事件 CustomEvent
  • AUTOSAR进阶图解==>AUTOSAR_SRS_FlashTest
  • EasyGBS的两种录像回看
  • ROS主控和stm32小车底盘通过串口进行通讯