数据预处理(异常值处理与归一化)
Excel 数据归一化处理代码讲解
MATLAB 代码实现了对 Excel 文件中的数据进行归一化处理,并将结果保存为新的 Excel 文件。归一化是数据预处理中常用的步骤,目的是将不同特征的取值范围标准化,消除量纲差异,从而提高后续分析或建模的效果。以下是对代码的详细讲解:
1. 导入数据
filename = '1945-2023.xlsx';
data = readtable(filename);
- 文件读取:使用
readtable
函数从 Excel 文件'1945-2023.xlsx'
中读取数据,并存储在表格变量data
中。 - 数据结构:
readtable
会自动检测 Excel 文件的内容,并将其读取为 MATLAB 中的表格数据格式(table)。这种格式便于后续的数据处理和访问。
2. 获取表头
headers = data.Properties.VariableNames;
- 表头提取:通过
Properties.VariableNames
获取数据表中的列名(即表头)。这些列名会存储在headers
变量中,用于后续操作。 - 示例:假设 Excel 文件中的表头为
{'Year', 'Temperature', 'Rainfall'}
,则headers
为一个包含这些列名的字符串数组。
3. 初始化归一化后的表格
normalizedData = data;
- 初始化新表格:复制原始数据到
normalizedData
,这个变量用于存储归一化处理后的数据。这样可以保留原始数据不变,方便后续比较和验证。
4. 逐列归一化处理
for i = 1:width(data)
col = table2array(data(:,i)); % 将表格列转换为数组
col_norm = (col - min(col)) / (max(col) - min(col)); % 归一化处理
normalizedData.(headers{i}) = col_norm; % 将归一化结果存储回对应列
end
-
逐列遍历:使用
for
循环遍历表格中的每一列。width(data)
返回表格的列数。
-
列转换为数组:
table2array
将当前列从表格格式转换为数组格式,方便进行数学运算。 -
归一化处理:
-
存储归一化结果:将归一化后的数组
col_norm
存储回normalizedData
表格中的对应列。
5. 保存归一化后的数据
writetable(normalizedData, 'normalized_data.xlsx');
- 写入 Excel 文件:使用
writetable
函数将归一化后的数据表格normalizedData
保存到新的 Excel 文件'normalized_data.xlsx'
中。 - 文件输出:输出的文件包含原始表头和归一化后的数据,便于后续的使用和分析。
总结
这段代码实现了以下功能:
- 从 Excel 文件中读取原始数据。
- 对每一列数据进行归一化处理,将其缩放到
[0, 1]
区间。 - 将归一化后的数据保存为新的 Excel 文件。
优点
- 简洁:代码结构清晰,每一步处理都很直观。
- 通用性强:可以处理任意结构的 Excel 表格,只要所有列都是数值型数据。
- 保留原始表头:输出的文件保留了原始表头,便于后续分析。
改进建议
- 异常值处理:归一化前,可以考虑检测并处理异常值(如 NaN 或 Inf 值),避免影响归一化结果。
- 数据类型检查:如果 Excel 文件包含非数值型列(如文本列),应在归一化前进行检查并跳过这些列。
- 归一化范围调整:默认归一化范围为
[0, 1]
,但可以根据需求调整为其他范围(如[-1, 1]
)。
使用教程
假设输入 Excel 文件包含以下数据:
Year | Temperature | Rainfall |
---|---|---|
1945 | 15.3 | 200 |
1950 | 16.7 | 220 |
1960 | 14.8 | 180 |
归一化后的输出文件为:
Year | Temperature | Rainfall |
---|---|---|
0 | 0.3333 | 0.3333 |
0.5 | 1 | 1 |
1 | 0 | 0 |
这种标准化后的数据可以作为机器学习模型的输入,消除了不同特征量纲的影响。
全部代码:
filename = '1945-2023.xlsx';
data = readtable(filename);
% 获取表头
headers = data.Properties.VariableNames;
% 初始化归一化后的表格
normalizedData = data;
% 对每一列进行归一化处理
for i = 1:width(data)
col = table2array(data(:,i));
col_norm = (col - min(col)) / (max(col) - min(col));
normalizedData.(headers{i}) = col_norm;
end
% 将归一化数据写入新的Excel文件
writetable(normalizedData, 'normalized_data.xlsx');
异常值检测与替换MATLAB 代码讲解
代码从 Excel 文件中读取数据,对多个变量进行异常值检测,并通过中位数替换异常值。代码还包含了绘制箱线图(Boxplot),用于可视化原始数据和处理后数据的分布情况。以下是对代码各部分的详细讲解:
1. 数据导入
filename = 'normalized_data.xlsx';
sheet = 1;
data = readmatrix(filename, 'Sheet', sheet, 'Range', 'A2:H69131');
- 文件读取:使用
readmatrix
从 Excel 文件'normalized_data.xlsx'
中读取数据。Sheet
指定要读取的工作表,这里为第一个工作表。Range
指定要读取的数据范围,这里为A2:H69131
,表示从第二行开始读取,直到第69131行,共8列数据。
2. 数据分离与合并
LON = data(:, 1);
LAT = data(:, 2);
Strength = data(:, 3);
grade = data(:, 4);
wind_velocity = data(:, 5);
pressure = data(:, 6);
Direction = data(:, 7);
speed = data(:, 8);
all_data = [LON, LAT, Strength, grade, wind_velocity, pressure, Direction, speed];
- 分离列数据:将数据中的每一列分别赋值给对应的变量。
- 合并数据:将所有列数据合并为一个矩阵
all_data
,便于后续操作和可视化。
3. 绘制原始数据的箱线图
figure;
boxplot(all_data, 'Labels', {'LON', 'LAT', 'Strength', 'grade', 'wind_velocity', 'pressure', 'Direction', 'speed'}, ...
'Widths', 0.7, 'Whisker', 1.5);
title('Boxplot with Outliers');
xlabel('Variables');
ylabel('Values');
grid on;
set(gca, 'FontSize', 12, 'FontWeight', 'bold');
set(findobj(gca, 'type', 'line'), 'linew', 1.5);
h = findobj(gca, 'Tag', 'Box');
for j = 1:length(h)
patch(get(h(j), 'XData'), get(h(j), 'YData'), [0.7, 0.9, 1], 'FaceAlpha', .7);
end
- 箱线图(Boxplot):箱线图用于显示数据分布和异常值(outliers)。
Labels
参数为箱线图的每个箱子添加标签。Widths
控制箱子宽度,Whisker
控制箱线图的须线长度(默认1.5倍四分位距)。
- 美化图形:
set
函数调整字体大小和线条粗细。- 使用
patch
函数为每个箱子添加半透明填充颜色,提高可视化效果。
4. 异常值检测与统计
outliers = isoutlier(all_data);
for i = 1:size(all_data, 2)
fprintf('Column %d has %d outliers\n', i, sum(outliers(:, i)));
end
- 异常值检测:使用
isoutlier
函数检测每列中的异常值,返回逻辑数组outliers
,其中true
表示该数据点为异常值。 - 统计异常值:遍历每列,计算并打印异常值的数量。
5. 异常值替换
corrected_data = all_data;
for i = 1:size(all_data, 2)
col_median = median(all_data(:, i), 'omitnan'); % 计算中位数
outlier_idx = isoutlier(all_data(:, i)); % 获取异常值索引
corrected_data(outlier_idx, i) = col_median; % 用中位数替换异常值
end
- 异常值替换策略:使用中位数替换异常值。
- 中位数(Median)是一种稳健的统计量,受异常值影响较小,因此适合作为替换值。
omitnan
参数用于忽略NaN
值,确保计算正确。
- 替换过程:遍历每列数据,找到异常值索引并用中位数替换对应的异常值。
6. 绘制处理后数据的箱线图
figure;
boxplot(corrected_data, 'Labels', {'LON', 'LAT', 'Strength', 'grade', 'wind_velocity', 'pressure', 'Direction', 'speed'}, ...
'Widths', 0.7, 'Whisker', 1.5);
title('Boxplot after Replacing Outliers');
xlabel('Variables');
ylabel('Values');
grid on;
set(gca, 'FontSize', 12, 'FontWeight', 'bold');
set(findobj(gca, 'type', 'line'), 'linew', 1.5);
h = findobj(gca, 'Tag', 'Box');
for j = 1:length(h)
patch(get(h(j), 'XData'), get(h(j), 'YData'), [0.7, 0.9, 1], 'FaceAlpha', .7);
end
- 绘制新的箱线图:展示替换异常值后的数据分布,便于与原始数据进行对比。
- 可视化调整:与之前相同,使用
patch
为箱线图添加颜色填充,改善图表效果。
总结
这段代码的主要功能包括:
- 从 Excel 文件中读取数据,并对每列数据绘制箱线图。
- 检测异常值,并统计每列数据中的异常值数量。
- 使用中位数替换异常值,避免异常值对数据分析或模型训练的影响。
- 绘制处理后的箱线图,展示替换异常值后的数据分布情况。
优点
- 稳健性:使用中位数替换异常值,能有效减少异常值对数据分布的影响。
- 可视化:通过箱线图直观地展示异常值的处理效果。
- 易于扩展:可以轻松修改代码以处理不同的数据文件或列数。
改进建议
- 异常值检测方法:除了使用
isoutlier
函数,还可以考虑使用其他方法,如基于标准差的检测或 Z-score 检测。 - 替换策略:除了中位数替换,还可以使用均值替换、插值法替换或删除异常值,具体选择取决于实际数据场景和分析需求。
- 性能优化:对于大规模数据集,可以考虑并行处理或分块处理以提高效率。
使用教程
将归一化的表格导入后,修改代码中有列名的地方即可!
全部代码
filename = 'normalized_data.xlsx';
sheet = 1;
data = readmatrix(filename, 'Sheet', sheet, 'Range', 'A2:H69131');
LON = data(:, 1);
LAT = data(:, 2);
Strength = data(:, 3);
grade = data(:, 4);
wind_velocity = data(:, 5);
pressure = data(:, 6);
Direction = data(:, 7);
speed = data(:, 8);
all_data = [LON, LAT, Strength, grade, wind_velocity, pressure, Direction, speed];
figure;
boxplot(all_data, 'Labels', {'LON', 'LAT', 'Strength', 'grade', 'wind_velocity', 'pressure', 'Direction', 'speed'}, ...
'Widths', 0.7, 'Whisker', 1.5);
title('Boxplot with Outliers');
xlabel('Variables');
ylabel('Values');
grid on;
set(gca, 'FontSize', 12, 'FontWeight', 'bold');
set(findobj(gca, 'type', 'line'), 'linew', 1.5);
h = findobj(gca, 'Tag', 'Box');
for j=1:length(h)
patch(get(h(j), 'XData'), get(h(j), 'YData'), [0.7, 0.9, 1], 'FaceAlpha', .7);
end
outliers = isoutlier(all_data);
for i = 1:size(all_data, 2)
fprintf('Column %d has %d outliers\n', i, sum(outliers(:, i)));
end
corrected_data = all_data;
for i = 1:size(all_data, 2)
col_median = median(all_data(:, i), 'omitnan');
outlier_idx = isoutlier(all_data(:, i));
corrected_data(outlier_idx, i) = col_median;
end
figure;
boxplot(corrected_data, 'Labels', {'LON', 'LAT', 'Strength', 'grade', 'wind_velocity', 'pressure', 'Direction', 'speed'}, ...
'Widths', 0.7, 'Whisker', 1.5);
title('Boxplot after Replacing Outliers');
xlabel('Variables');
ylabel('Values');
grid on;
set(gca, 'FontSize', 12, 'FontWeight', 'bold');
set(findobj(gca, 'type', 'line'), 'linew', 1.5);
h = findobj(gca, 'Tag', 'Box');
for j=1:length(h)
patch(get(h(j), 'XData'), get(h(j), 'YData'), [0.7, 0.9, 1], 'FaceAlpha', .7);
end