箱线图法是异常值检测的通用方法(适配任意数据分布),核心通过四分位数(IQR)判定异常值,以下是可直接套用的完整代码,包含数据导入、统计量计算、异常值定位、可视化标注、异常值处理全流程。
一、完整代码(直接复制可用)
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% 箱线图法异常值检测完整流程
% 适用场景:任意分布的数值型数据(单变量)
% 数据格式:CSV文件(可替换为Excel/TXT等格式)
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% 1. 数据导入与预处理(基础准备)
% 导入CSV数据(替换为你的数据路径)
data = readtable('待检测数据.csv');
% 筛选需要检测的数值列(示例:选择第2列,可根据实际修改列索引/列名)
detect_col_name = '传感器温度'; % 也可直接用列索引:detect_col = data(:,2);
detect_col = data.(detect_col_name);
% 处理缺失值(中位数填充,避免NaN干扰计算)
detect_col_filled = fillmissing(detect_col, 'constant', median(detect_col, 'omitNaN'));
% 转换为数组(方便后续计算)
detect_arr = table2array(detect_col_filled);
%% 2. 计算箱线图核心统计量(判定异常值的关键)
% 计算四分位数Q1(25%)、Q3(75%)
q = quantile(detect_arr, [0.25, 0.75]);
Q1 = q(1); % 下四分位数
Q3 = q(2); % 上四分位数
% 计算四分位距IQR
IQR_val = Q3 - Q1;
% 计算异常值判定边界(1.5*IQR是行业通用标准)
lower_bound = Q1 - 1.5 * IQR_val; % 下边界
upper_bound = Q3 + 1.5 * IQR_val; % 上边界
%% 3. 定位异常值(索引+具体数值)
% 生成逻辑矩阵:1=异常值,0=正常值
outlier_logic = (detect_arr < lower_bound) | (detect_arr > upper_bound);
% 提取异常值行索引(用于定位原始数据中的异常行)
outlier_idx = find(outlier_logic);
% 提取异常值具体数值
outlier_values = detect_arr(outlier_idx);
%% 4. 可视化:绘制箱线图并标注异常值(直观验证)
figure('Color','white'); % 设置画布背景为白色
% 绘制箱线图(Whisker=1.5对应异常值判定标准)
boxplot(detect_arr, 'Whisker', 1.5, 'Label', detect_col_name);
title('箱线图法异常值检测结果','FontSize',12);
xlabel('检测指标','FontSize',10);
ylabel('数值','FontSize',10);
grid on; % 显示网格线,便于读取数值
% 红色圆点标注异常值(突出显示)
hold on;
plot(ones(size(outlier_values)), outlier_values, 'ro', 'MarkerSize', 6, 'MarkerFaceColor','r');
hold off;
%% 5. 输出异常值信息(便于核对)
disp('==================== 异常值检测结果 ====================');
disp(['检测列:', detect_col_name]);
disp(['下四分位数(Q1):', num2str(Q1)]);
disp(['上四分位数(Q3):', num2str(Q3)]);
disp(['四分位距(IQR):', num2str(IQR_val)]);
disp(['异常值下边界:', num2str(lower_bound)]);
disp(['异常值上边界:', num2str(upper_bound)]);
disp(['检测到异常值数量:', num2str(length(outlier_idx))]);
if length(outlier_idx) > 0
disp(['异常值行索引:', num2str(outlier_idx)]);
disp(['异常值具体数值:', num2str(outlier_values)]);
else
disp('未检测到异常值');
end
%% 6. 异常值处理(3种常用方式,按需选择)
% 方式1:删除异常值(适用于异常值占比<1%)
data_clean_del = data(~outlier_logic, :);
% 方式2:替换为边界值(保留数据量,适用于连续数据)
data_clean_replace = data;
replace_arr = table2array(data_clean_replace.(detect_col_name));
replace_arr(outlier_logic) = upper_bound; % 上边界替换(下异常值可换lower_bound)
data_clean_replace.(detect_col_name) = array2table(replace_arr);
% 方式3:缩尾处理(替换为99%/1%分位数,适用于偏态数据)
p01 = quantile(detect_arr, 0.01);
p99 = quantile(detect_arr, 0.99);
data_clean_winsor = data;
winsor_arr = table2array(data_clean_winsor.(detect_col_name));
winsor_arr(winsor_arr < p01) = p01;
winsor_arr(winsor_arr > p99) = p99;
data_clean_winsor.(detect_col_name) = array2table(winsor_arr);
%% 7. 保存清洗后的数据(按需选择)
writetable(data_clean_del, '清洗后_删除异常值.csv');
% writetable(data_clean_replace, '清洗后_替换边界值.csv');
% writetable(data_clean_winsor, '清洗后_缩尾处理.csv');
disp('==================== 数据清洗完成 ====================');
二、代码逐行解析(新手易懂)
1. 数据导入与预处理
data = readtable('待检测数据.csv'):导入CSV格式数据,若为Excel文件可替换为readtable('数据.xlsx');detect_col = data.(detect_col_name):按列名选择检测列,也可直接用列索引(如data(:,2));fillmissing(...):中位数填充缺失值,避免NaN导致后续计算出错;table2array(...):将表格列转换为数组,简化统计计算。
2. 核心统计量计算
quantile(detect_arr, [0.25, 0.75]):计算25%和75%分位数(Q1、Q3);IQR_val = Q3 - Q1:四分位距,反映数据中间50%的离散程度;lower/upper_bound:异常值判定边界,1.5IQR是通用标准,若需严格检测可改为3IQR(识别极端异常值)。
3. 异常值定位
outlier_logic:生成逻辑矩阵,快速标记异常值位置;find(outlier_logic):提取异常值的行索引,方便定位原始数据中的异常行;outlier_values:提取异常值具体数值,便于人工核验。
4. 可视化标注
boxplot(...):绘制箱线图,默认Whisker=1.5,与异常值判定标准一致;plot(ones(...), outlier_values, 'ro'):用红色实心圆点标注异常值,直观查看异常值分布。
5. 异常值处理
- 删除异常值:最简单的方式,适合异常值占比极低(<1%)的场景;
- 边界值替换:避免数据量减少,适合连续数据(如传感器读数);
- 缩尾处理:替换为99%/1%分位数,适合偏态数据(如销量、收入)。
三、使用注意事项
- 数据路径替换:将代码中
待检测数据.csv替换为你的实际数据路径(绝对路径/相对路径均可); - 检测列调整:修改
detect_col_name为你的数据列名(或直接用列索引); - 异常值核验:检测出的“异常值”需结合业务场景验证(如传感器故障值是真异常,促销期销量极值是正常值);
- 多列检测:若需检测多列数据,可套入
for循环(示例):
% 多列检测示例:检测第2-4列
num_cols = 2:4;
for i = num_cols
detect_col = data(:,i);
% 后续复制上述2-6步代码即可
end