C++代码实现MATLAB中的removeoutliers函数功能
// removeoutliers.cpp// 对应 MATLAB rmoutliers(A) 的 C++ 实现 + 演示程序// 编译: g++ -std=c++17 -O2 -o removeoutliers_demo#include<iostream>#include<iomanip>#include<vector>#include<algorithm>#include<cmath>#include<numeric>#include<stdexcept>#include<string>/** * 对应 MATLAB rmoutliers(A) 的 C++ 实现 * 默认方法:MAD(中位数绝对偏差),阈值因子 3 * 支持方法:median(MAD)、mean(均值±标准差)、quartiles(四分位数) */classRemoveOutliers{public:// 检测方法enumclassMethod{Median,// 默认,MADMean,// 均值 ± 3σQuartiles// 四分位数法};structOptions{Method method=Method::Median;doublethresholdFactor=3.0;// median/mean 默认 3;quartiles 默认 1.5booluseScaledMAD=true;// 是否使用换算 MAD(乘常数 c)intdim=1;// 1 按行移除,2 按列移除(矩阵)};structResult{std::vector<std::vector<double>>cleanedData;// 清洗后数据std::vector<bool>outlierMask;// 离群值逻辑掩码(展平)std::vector<int>removedIndices;// 被移除的行/列索引};public:/** * 对向量或矩阵进行离群值检测与移除 * @param data 输入数据(二维:行×列) * @param opts 选项 * @return 清洗后的数据及元信息 */staticResultprocess(conststd::vector<std::vector<double>>&data){returnprocess(data,Options{});}staticResultprocess(conststd::vector<std::vector<double>>&data,constOptions&opts){if(data.empty()||data[0].empty())throwstd::invalid_argument("Input data is empty.");constsize_t rows=data.size();constsize_t cols=data[0].size();// 校验:所有行长度一致for(constauto&row:data){if(row.size()!=cols)throwstd::invalid_argument("Rows have inconsistent lengths.");}Result result;if(opts.dim==1){// 按列检测,移除整行(MATLAB 默认行为)result=processByColumn(data,opts);}elseif(opts.dim==2){// 按行检测,移除整列result=processByRow(data,opts);}else{throwstd::invalid_argument("dim must be 1 or 2.");}returnresult;}// ========== 核心统计函数 ==========/** * 计算中位数(自动排序副本,不修改原数据) */staticdoublemedian(std::vector<double>v){if(v.empty())return0.0;size_t n=v.size();std::sort(v.begin(),v.end());if(n%2==1){returnv[n/2];}else{return0.5*(v[n/2-1]+v[n/2]);}}/** * 计算换算 MAD(Median Absolute Deviation) * scaledMAD = c * median(|x - median(x)|) * c = 1 / (sqrt(2) * erfcinv(3/2)) ≈ 1.482602218505602 */staticdoublescaledMAD(conststd::vector<double>&data){if(data.size()<2)return0.0;doublemed=median(data);std::vector<double>absDev;absDev.reserve(data.size());for(doublex:data){absDev.push_back(std::fabs(x-med));}doublerawMAD=median(absDev);// 换算常数 cconstdoublec=1.482602218505602;returnc*rawMAD;}/** * 计算算术均值 */staticdoublemean(conststd::vector<double>&data){if(data.empty())return0.0;doublesum=std::accumulate(data.begin(),data.end(),0.0);returnsum/static_cast<double>(data.size());}/** * 计算样本标准差(无偏估计,除以 n-1,与 MATLAB std 默认一致) */staticdoublestddev(conststd::vector<double>&data){size_t n=data.size();if(n<2)return0.0;doublem=mean(data);doublesqSum=0.0;for(doublex:data){doubled=x-m;sqSum+=d*d;}returnstd::sqrt(sqSum/static_cast<double>(n-1));}/** * 计算指定百分位数(线性插值法,与 MATLAB prctile 一致) */staticdoublepercentile(std::vector<double>v,doublep){if(v.empty())return0.0;if(p<=0.0)return*std::min_element(v.begin(),v.end());if(p>=100.0)return*std::max_element(v.begin(),v.end());std::sort(v.begin(),v.end());doublerank=(p/100.0)*(static_cast<double>(v.size())-1.0);size_t lo=static_cast<size_t>(std::floor(rank));size_t hi=static_cast<size_t>(std::ceil(rank));doublefrac=rank-static_cast<double>(lo);if(lo==hi)returnv[lo];returnv[lo]*(1.0-frac)+v[hi]*frac;}private:// ========== 按列处理(移除行) ==========staticResultprocessByColumn(conststd::vector<std::vector<double>>&data,constOptions&opts){constsize_t rows=data.size();constsize_t cols=data[0].size();std::vector<bool>rowOutlier(rows,false);// 对每一列独立检测for(size_t j=0;j<cols;++j){std::vector<double>colData;colData.reserve(rows);for(size_t i=0;i<rows;++i)colData.push_back(data[i][j]);std::vector<bool>colMask=detectOutliers(colData,opts);for(size_t i=0;i<rows;++i){if(colMask[i])rowOutlier[i]=true;// 任一列检出则移除整行}}// 构建结果Result res;res.outlierMask=rowOutlier;for(size_t i=0;i<rows;++i){if(rowOutlier[i]){res.removedIndices.push_back(static_cast<int>(i));}else{res.cleanedData.push_back(data[i]);}}returnres;}// ========== 按行处理(移除列) ==========staticResultprocessByRow(conststd::vector<std::vector<double>>&data,constOptions&opts){constsize_t rows=data.size();constsize_t cols=data[0].size();std::vector<bool>colOutlier(cols,false);for(size_t i=0;i<rows;++i){std::vector<bool>rowMask=detectOutliers(data[i],opts);for(size_t j=0;j<cols;++j){if(rowMask[j])colOutlier[j]=true;}}Result res;for(size_t i=0;i<rows;++i){std::vector<double>newRow;for(size_t j=0;j<cols;++j){if(!colOutlier[j])newRow.push_back(data[i][j]);}res.cleanedData.push_back(std::move(newRow));}for(size_t j=0;j<cols;++j){if(colOutlier[j])res.removedIndices.push_back(static_cast<int>(j));}res.outlierMask=colOutlier;returnres;}// ========== 离群值检测核心 ==========staticstd::vector<bool>detectOutliers(conststd::vector<double>&data,constOptions&opts){size_t n=data.size();std::vector<bool>mask(n,false);if(n<2)returnmask;switch(opts.method){caseMethod::Median:{doublemed=median(data);doublemadVal=opts.useScaledMAD?scaledMAD(data):[&](){std::vector<double>absDev;for(doublex:data)absDev.push_back(std::fabs(x-med));returnmedian(absDev);}();if(madVal<=0.0)returnmask;// 所有值相同,无离群值doublethr=opts.thresholdFactor*madVal;for(size_t i=0;i<n;++i){if(std::fabs(data[i]-med)>thr)mask[i]=true;}break;}caseMethod::Mean:{doublem=mean(data);doubles=stddev(data);if(s<=0.0)returnmask;doublethr=opts.thresholdFactor*s;for(size_t i=0;i<n;++i){if(std::fabs(data[i]-m)>thr)mask[i]=true;}break;}caseMethod::Quartiles:{doubleq1=percentile(data,25.0);doubleq3=percentile(data,75.0);doubleiqr=q3-q1;doublelower=q1-opts.thresholdFactor*iqr;doubleupper=q3+opts.thresholdFactor*iqr;for(size_t i=0;i<n;++i){if(data[i]<lower||data[i]>upper)mask[i]=true;}break;}}returnmask;}};// ============================ 演示主程序 ============================intmain(){// 示例数据(含离群值)std::vector<std::vector<double>>data={{1.0,1.0},// 0{34.0,0.0},// 1{35.0,35.0},// 2{35.0,35.0},// 3{33.0,33.0},// 4{34.0,34.0},// 5{160.0,160.0},// 6 离群值{38.0,38.0},// 7{35.0,35.0},// 8{95.0,35.0},// 9 第1列离群{36.0,36.0},// 10{150.0,150.0},// 11 离群值{39.0,39.0},// 12{41.0,41.0},// 13{42.0,40.0},// 14{0.0,0.0},// 15 离群值{200.0,200.0}// 16 离群值};// 默认 MAD 方法autoresult=RemoveOutliers::process(data);std::cout<<"=== 默认 MAD 方法(thresholdFactor=3)===\n";std::cout<<"被移除的行索引:";for(intidx:result.removedIndices)std::cout<<idx<<" ";std::cout<<"\n\n清洗后数据:\n";for(constauto&row:result.cleanedData){for(doublev:row)std::cout<<std::setw(6)<<v<<" ";std::cout<<"\n";}// 均值 ± 3σ 方法RemoveOutliers::Options meanOpt;meanOpt.method=RemoveOutliers::Method::Mean;autoresultMean=RemoveOutliers::process(data,meanOpt);std::cout<<"\n=== Mean 方法 ===\n移除行数:"<<resultMean.removedIndices.size()<<"\n";// 四分位数方法RemoveOutliers::Options quartOpt;quartOpt.method=RemoveOutliers::Method::Quartiles;quartOpt.thresholdFactor=1.5;autoresultQuart=RemoveOutliers::process(data,quartOpt);std::cout<<"\n=== Quartiles 方法(1.5×IQR)===\n移除行数:"<<resultQuart.removedIndices.size()<<"\n";return0;}

相关新闻

原生JavaScript表单与搜索框组件库:防抖、校验与本地存储实战解析

原生JavaScript表单与搜索框组件库:防抖、校验与本地存储实战解析

简介&#xff1a;6个精美的Web前端表单提交与搜索框示例&#xff0c;是一份面向初中级前端开发者、UI设计师及网站后台维护人员的实用参考。压缩包内含完整的表单与搜索页面源码&#xff0c;将CSS样式与jQuery脚本集中在HTML示例中&#xff0c;覆盖文本框、下拉菜单、复选框等常…

2026/11/15 2:41:22 阅读更多 →
基于PySpark+Hive+大模型的小红书评论情感分析与舆情预测系统设计

基于PySpark+Hive+大模型的小红书评论情感分析与舆情预测系统设计

动手做毕业设计的时候&#xff0c;能同时把PySpark、Hive、大模型这三个词凑到一个题目里&#xff0c;本身就说明这个题目不是那种随便改个爬虫就能糊弄的“水货”。小红书评论情感分析、笔记可视化、舆情预测&#xff0c;这套组合拳打下来&#xff0c;技术栈覆盖了数据采集、分…

2026/11/15 2:46:40 阅读更多 →
MySQL索引从原理到实战:B+树、执行计划与慢SQL调优

MySQL索引从原理到实战:B+树、执行计划与慢SQL调优

刚接手一个线上系统的时候&#xff0c;我遇到过一条查询跑两秒多的SQL&#xff0c;全表扫描扫了三百多万行&#xff0c;而业务要求响应在一百毫秒内。当时的我连EXPLAIN都不会看&#xff0c;被DBA指着鼻子说"你这表连索引都没建对"。从那以后&#xff0c;我把MySQL索…

2026/11/14 11:26:59 阅读更多 →

最新新闻

Electron桌面应用开发实战:从环境搭建到打包发布全流程

Electron桌面应用开发实战:从环境搭建到打包发布全流程

做前端这些年&#xff0c;我大部分时间都在跟浏览器标签页打交道&#xff0c;直到第一次把桌面应用跑起来&#xff0c;才发现原来自己一直被限制在地址栏和刷新按钮围起来的框框里。Electron这个词&#xff0c;最开始是在某段时间频繁出现在同事的讨论里&#xff0c;一个用HTML…

2026/11/14 5:13:29 阅读更多 →
滑盖智能锁T109深度解析:结构原理、安装调试与故障排查

滑盖智能锁T109深度解析:结构原理、安装调试与故障排查

简介&#xff1a;亚太天能T109滑盖智能锁产品说明书是一份PDF格式的官方技术文档&#xff0c;主要面向智能锁安装人员、终端用户及售后维护者&#xff0c;帮助快速掌握产品安装、配置与常见故障处理。全包仅1个PDF文件&#xff0c;大小4.37MB&#xff0c;内容结构清晰&#xff…

2026/11/14 5:13:29 阅读更多 →
PMSM弱磁控制原理与Simulink建模:高速AGV驱动系统设计指南

PMSM弱磁控制原理与Simulink建模:高速AGV驱动系统设计指南

上个月我在调试一台高速AGV的驱动系统&#xff0c;整车要求空载跑到8m/s&#xff0c;电机转速已经拉到额定点&#xff0c;驱动器的输出电压也顶到了母线电压极限附近。再往上踩速度指令&#xff0c;转速纹丝不动&#xff0c;三相电流反而开始震荡。那会儿我的第一反应就是&…

2026/11/14 5:13:29 阅读更多 →
C++核心知识点:从内存管理到STL的实战指南

C++核心知识点:从内存管理到STL的实战指南

C 这门语言我前前后后折腾了十几年&#xff0c;用它写过嵌入式驱动、做过游戏服务端&#xff0c;也搭过基础组件库。每次看到新人一头扎进"C 核心知识点"这个搜索词&#xff0c;我其实挺感慨的——这门语言的难点从来不是语法多&#xff0c;而是知识点之间的耦合太深…

2026/11/13 22:08:41 阅读更多 →
T109滑盖智能锁怎么装?安装调试与故障排查全攻略

T109滑盖智能锁怎么装?安装调试与故障排查全攻略

简介&#xff1a;亚太天能T109滑盖智能锁产品说明书以PDF格式发布&#xff0c;适合智能锁用户、安装人员与售后维修人员阅读。内容围绕T109系列指纹密码刷卡锁展开&#xff0c;先介绍前面板、后面板、锁体、机械钥匙、电池盒盖等部件名称与功能&#xff0c;再给出完整安装步骤&…

2026/11/14 2:41:37 阅读更多 →
LLM知识降熵:从信息垄断到理解权下放

LLM知识降熵:从信息垄断到理解权下放

你有没有过这种经历&#xff1a;翻开源码注释、论文摘要或者一份专业报告&#xff0c;每个字都认识&#xff0c;连在一起却像天书。想找人聊聊&#xff0c;身边要么没人懂&#xff0c;要么懂的懒得跟你解释。后来我试着把同一段内容丢给一个大语言模型&#xff0c;几秒钟之后&a…

2026/11/14 5:13:29 阅读更多 →

日新闻

周新闻

月新闻