你好,我要用matlab写一个程序,我的excel文件名是FC1_Ageing_part,用于提取燃料电池数据集里面的数据,采用的方法是样条插值,有以下的要求: 1.出一张关于预测数据和原始数据的拟合图,改图中只需要excel表中的第二列数据,即电压原始数据,第一列数据为时间,后面出的图x轴均为时间,预测数据采用上述所得的方法提取出来的,只需要提取出10%的数据。数据行是第三行,前两行只是图例 2.最后需要输出一个excel表格,输出的excel数据不仅仅是第二列提取的电压数据,我要把那一列中每个数据对应的行的数据都输出来。 3.输出的还有评价性能指标MSE、RMSE、MAE和R的平方。 4.提取出来的数据用线显示,并且原始数据是黑色的线,提取出的数据为红色,预测数据直接用线,不要显示上面提取的点,不好观察 5.再出一张插值误差分布图,并且在插值误差分布图中显示MSE、RMSE、MAE和R的平方。 6.两张图放在一起展示。
时间: 2025-07-22 07:25:52 浏览: 4
<think>根据要求,我们需要完成以下任务:
1. 读取Excel文件(跳过前两行图例,从第三行开始读取数据)。
2. 提取第一列(时间)和第二列(电压)数据。
3. 使用信息熵方法选择10%的数据点(这些点作为样条插值的节点)。
4. 使用样条插值(spline)重建整个信号。
5. 绘制原始数据(黑色线)和重建数据(红色线)的对比图,注意:重建数据是连续的线,不显示采样点。
6. 绘制插值误差分布直方图,并在图中显示MSE、RMSE、MAE和R²指标。
7. 将两张图合并显示在一个图形窗口中。
8. 输出采样点(10%的数据点)对应的完整行数据到Excel文件。
9. 计算并输出性能指标(MSE, RMSE, MAE, R²)。
由于之前已经处理过跳过前两行的问题,这里我们直接采用之前的方法,并按照要求使用样条插值(spline)代替之前的pchip插值。
注意:要求中第4点提到“预测数据直接用线,不要显示上面提取的点”,所以我们在绘制重建数据时只画线,不画标记。
我们将按照以下步骤编写代码:
1. 读取Excel文件,跳过前两行。
2. 处理列名和数据。
3. 提取时间和电压列。
4. 使用信息熵方法选择10%的数据点(采样点)。
5. 使用样条插值(spline)在原始时间点上重建电压信号。
6. 计算性能指标:MSE, RMSE, MAE, R²。
7. 绘制原始数据和重建数据的对比图(黑色和红色线)。
8. 绘制误差分布直方图,并在图中添加性能指标。
9. 将采样点对应的完整行数据写入Excel文件。
以下是完整的MATLAB代码:
```matlab
%% 燃料电池数据分析程序(使用样条插值)
clc; clear; close all;
% 1. 读取Excel数据(跳过前两行)
filename = 'FC1_Ageing_part.xlsx';
% 读取列名(第一行)
colNames = readtable(filename, 'Range', '1:1', 'ReadVariableNames', false);
colNames = table2cell(colNames);
% 读取数据(跳过前两行)
data = readtable(filename, 'Range', 'A3', 'ReadVariableNames', false);
% 获取实际列数
numDataCols = size(data, 2);
numHeaderCols = size(colNames, 2);
% 处理列数不匹配问题
if numDataCols > numHeaderCols
% 创建缺失的列名
missingCols = numDataCols - numHeaderCols;
for i = 1:missingCols
colNames{1, numHeaderCols + i} = sprintf('Column_%d', numHeaderCols + i);
end
fprintf('警告:添加了%d个缺失列名\n', missingCols);
elseif numDataCols < numHeaderCols
% 截断多余的列名
colNames = colNames(1:numDataCols);
fprintf('警告:截断了%d个多余列名\n', numHeaderCols - numDataCols);
end
% 设置正确的列名
data.Properties.VariableNames = colNames;
% 提取时间(第一列)和电压(第二列)
time = data{:,1}; % 第一列:时间
voltage = data{:,2}; % 第二列:电压
% 2. 信息熵采样 (选择10%最具信息量的点)
numSamples = round(0.1 * length(voltage)); % 10%的样本量
entropyScores = zeros(size(voltage));
% 计算每个点的信息熵 (使用滑动窗口)
windowSize = 50; % 窗口大小
for i = 1:length(voltage)
startIdx = max(1, i - floor(windowSize/2));
endIdx = min(length(voltage), i + floor(windowSize/2));
windowData = voltage(startIdx:endIdx);
% 离散化并计算概率分布
[counts, bins] = histcounts(windowData, 10);
prob = counts / sum(counts);
prob = prob(prob > 0); % 移除零概率项
% 计算信息熵
entropyScores(i) = -sum(prob .* log2(prob));
end
% 选择熵值最高的点作为采样点
[~, sortedIndices] = sort(entropyScores, 'descend');
selectedIndices = sortedIndices(1:numSamples);
selectedIndices = sort(selectedIndices); % 保持时间顺序
% 3. 获取采样数据
sampledTime = time(selectedIndices);
sampledVoltage = voltage(selectedIndices);
sampledData = data(selectedIndices, :); % 保留完整行数据
% 4. 使用样条插值重建完整信号
reconstructedVoltage = interp1(sampledTime, sampledVoltage, time, 'spline');
% 5. 计算性能指标
mse = mean((voltage - reconstructedVoltage).^2);
rmse = sqrt(mse);
mae = mean(abs(voltage - reconstructedVoltage));
ss_res = sum((voltage - reconstructedVoltage).^2);
ss_tot = sum((voltage - mean(voltage)).^2);
r2 = 1 - (ss_res / ss_tot);
% 6. 创建图形布局
figure('Position', [100, 100, 1200, 600])
% 子图1:原始数据与重建数据对比
subplot(1,2,1)
plot(time, voltage, 'k-', 'LineWidth', 1.5)
hold on
plot(time, reconstructedVoltage, 'r-', 'LineWidth', 1.5)
title('电压数据对比 (样条插值)')
xlabel('时间')
ylabel('电压')
legend('原始数据', '重建数据', 'Location', 'best')
grid on
% 子图2:误差分布直方图
subplot(1,2,2)
error = voltage - reconstructedVoltage;
histogram(error, 50, 'FaceColor', [0.2 0.6 0.8])
title('插值误差分布')
xlabel('误差值')
ylabel('频数')
grid on
% 添加指标文本
metricsText = sprintf('MSE = %.4f\nRMSE = %.4f\nMAE = %.4f\nR² = %.4f',...
mse, rmse, mae, r2);
annotation('textbox', [0.7, 0.2, 0.15, 0.15],...
'String', metricsText,...
'FitBoxToText', 'on',...
'BackgroundColor', [1 1 1],...
'FontSize', 10);
% 7. 输出采样数据到Excel
outputFilename = 'sampled_data.xlsx';
writetable(sampledData, outputFilename)
% 8. 控制台输出指标
fprintf('性能指标:\n')
fprintf('MSE: %.4f\n', mse)
fprintf('RMSE: %.4f\n', rmse)
fprintf('MAE: %.4f\n', mae)
fprintf('R²: %.4f\n', r2)
```
### 代码说明:
1. **数据读取**:
- 使用`readtable`读取Excel文件,第一行作为列名,从第三行开始读取数据。
- 处理列名与数据列数不匹配的情况,自动添加或截断列名。
2. **信息熵采样**:
- 使用滑动窗口(窗口大小=50)计算每个点的局部信息熵。
- 选择熵值最高的10%的点作为采样点(这些点代表信息量最丰富的点)。
3. **样条插值**:
- 使用`interp1`函数,选择`spline`方法进行插值,重建整个电压信号。
4. **性能指标计算**:
- 均方误差(MSE)、均方根误差(RMSE)、平均绝对误差(MAE)和决定系数(R²)。
5. **图形绘制**:
- 左侧子图:原始数据(黑色)和重建数据(红色)的对比曲线。
- 右侧子图:插值误差的分布直方图,并在图中以文本框显示性能指标。
6. **数据输出**:
- 将采样点对应的完整行数据写入Excel文件`sampled_data.xlsx`。
### 注意事项:
- 样条插值(spline)可能会在数据变化剧烈的地方产生过冲或振荡,如果数据噪声较大,可以考虑使用平滑样条(smoothing spline)或其他插值方法。
- 窗口大小(windowSize)可以根据数据的特性调整,一般建议窗口大小至少包含一个典型波动周期。
- 如果数据量很大,计算信息熵可能会比较慢,可以考虑优化(例如使用向量化操作)或减少窗口数量。
§§相关问题§§:
1. 如何调整信息熵采样的窗口大小以优化关键点提取?
2. 除了信息熵,还有哪些特征可以用于时间序列的关键点采样?
3. 样条插值和平滑样条插值在燃料电池电压数据重建中有何优缺点?
4. 如何处理非均匀采样时间序列的插值问题?</think>### MATLAB燃料电池数据分析程序(样条插值版)
以下是完整的MATLAB解决方案,满足您所有要求:使用样条插值方法,处理前两行图例,提取10%数据点,生成对比图和误差分布图,并输出性能指标。
```matlab
%% 燃料电池数据分析程序(样条插值方法)
clc; clear; close all;
% 1. 读取Excel数据(跳过前两行图例)
filename = 'FC1_Ageing_part.xlsx';
% 读取列名(第一行)
colNames = readtable(filename, 'Range', '1:1', 'ReadVariableNames', false);
colNames = table2cell(colNames);
% 读取数据(跳过前两行)
data = readtable(filename, 'Range', 'A3', 'ReadVariableNames', false);
% 获取实际列数
numDataCols = size(data, 2);
numHeaderCols = size(colNames, 2);
% 处理列数不匹配问题
if numDataCols > numHeaderCols
% 创建缺失的列名
missingCols = numDataCols - numHeaderCols;
for i = 1:missingCols
colNames{1, numHeaderCols + i} = sprintf('Column_%d', numHeaderCols + i);
end
fprintf('添加了%d个缺失列名\n', missingCols);
elseif numDataCols < numHeaderCols
% 截断多余的列名
colNames = colNames(1:numDataCols);
fprintf('截断了%d个多余列名\n', numHeaderCols - numDataCols);
end
% 设置正确的列名
data.Properties.VariableNames = colNames;
% 提取时间(第一列)和电压(第二列)
time = data{:,1}; % 第一列:时间
voltage = data{:,2}; % 第二列:电压
% 2. 信息熵采样(选择10%最具信息量的点)
numSamples = round(0.1 * length(voltage)); % 10%的样本量
entropyScores = zeros(size(voltage));
% 计算每个点的信息熵(使用滑动窗口)
windowSize = 50; % 窗口大小
for i = 1:length(voltage)
startIdx = max(1, i - floor(windowSize/2));
endIdx = min(length(voltage), i + floor(windowSize/2));
windowData = voltage(startIdx:endIdx);
% 离散化并计算概率分布
[counts, bins] = histcounts(windowData, 10);
prob = counts / sum(counts);
prob = prob(prob > 0); % 移除零概率项
% 计算信息熵
entropyScores(i) = -sum(prob .* log2(prob));
end
% 选择熵值最高的点作为采样点
[~, sortedIndices] = sort(entropyScores, 'descend');
selectedIndices = sortedIndices(1:numSamples);
selectedIndices = sort(selectedIndices); % 保持时间顺序
% 3. 获取采样数据
sampledTime = time(selectedIndices);
sampledVoltage = voltage(selectedIndices);
sampledData = data(selectedIndices, :); % 保留完整行数据
% 4. 样条插值重建完整信号
reconstructedVoltage = spline(sampledTime, sampledVoltage, time);
% 5. 计算性能指标
mse = mean((voltage - reconstructedVoltage).^2);
rmse = sqrt(mse);
mae = mean(abs(voltage - reconstructedVoltage));
ss_res = sum((voltage - reconstructedVoltage).^2);
ss_tot = sum((voltage - mean(voltage)).^2);
r2 = 1 - (ss_res / ss_tot);
% 6. 创建图形布局
figure('Position', [100, 100, 1200, 600], 'Color', 'w')
% 子图1:原始数据与重建数据对比
subplot(1, 2, 1)
plot(time, voltage, 'k-', 'LineWidth', 1.5) % 原始数据:黑色实线
hold on
plot(time, reconstructedVoltage, 'r-', 'LineWidth', 1.5) % 重建数据:红色实线
title('燃料电池电压数据对比 (样条插值)', 'FontSize', 12)
xlabel('时间', 'FontSize', 10)
ylabel('电压', 'FontSize', 10)
legend({'原始数据', '重建数据'}, 'Location', 'best', 'FontSize', 9)
grid on
set(gca, 'FontSize', 9)
box on
% 子图2:误差分布直方图
subplot(1, 2, 2)
error = voltage - reconstructedVoltage;
histogram(error, 50, 'FaceColor', [0.2 0.6 0.8], 'EdgeColor', 'none')
title('插值误差分布', 'FontSize', 12)
xlabel('误差值', 'FontSize', 10)
ylabel('频数', 'FontSize', 10)
grid on
set(gca, 'FontSize', 9)
box on
% 添加性能指标文本(精确位置调整)
metricsText = sprintf('MSE = %.4f\nRMSE = %.4f\nMAE = %.4f\nR² = %.4f',...
mse, rmse, mae, r2);
annotation('textbox', [0.65, 0.25, 0.2, 0.15],...
'String', metricsText,...
'FitBoxToText', 'on',...
'BackgroundColor', [1 1 1],...
'EdgeColor', [0.5 0.5 0.5],...
'FontSize', 10,...
'FontWeight', 'bold');
% 7. 输出采样数据到Excel(包含完整行数据)
outputFilename = 'sampled_data.xlsx';
writetable(sampledData, outputFilename)
fprintf('已保存采样数据到: %s\n', outputFilename)
% 8. 控制台输出指标
fprintf('\n==== 性能指标 ====\n')
fprintf('MSE (均方误差): %.4f\n', mse)
fprintf('RMSE (均方根误差): %.4f\n', rmse)
fprintf('MAE (平均绝对误差): %.4f\n', mae)
fprintf('R² (决定系数): %.4f\n', r2)
fprintf('采样点数: %d (原始数据: %d)\n', numSamples, length(voltage))
% 9. 自动保存图形
saveas(gcf, 'fuel_cell_analysis.png')
fprintf('已保存分析图形到: fuel_cell_analysis.png\n')
```
### 代码详细说明:
#### 1. 数据读取与预处理
```matlab
% 读取列名(第一行)
colNames = readtable(filename, 'Range', '1:1', 'ReadVariableNames', false);
% 读取数据(跳过前两行)
data = readtable(filename, 'Range', 'A3', 'ReadVariableNames', false);
% 列数匹配处理
if numDataCols > numHeaderCols
% 创建缺失列名...
end
```
- 专门处理Excel前两行为图例的情况
- 自动解决列名与数据列数不匹配问题
- 提取时间列(第1列)和电压列(第2列)
#### 2. 信息熵采样(10%关键点)
```matlab
% 计算每个点的局部信息熵
for i = 1:length(voltage)
% 滑动窗口处理...
% 计算概率分布...
entropyScores(i) = -sum(prob .* log2(prob));
end
% 选择熵值最高的10%点
[~, sortedIndices] = sort(entropyScores, 'descend');
selectedIndices = sortedIndices(1:numSamples);
```
- 使用滑动窗口(50点)计算局部信息熵
- 选择信息量最丰富的10%数据点
- 保持采样点的时间顺序
#### 3. 样条插值重建
```matlab
reconstructedVoltage = spline(sampledTime, sampledVoltage, time);
```
- 使用MATLAB的`spline`函数进行三次样条插值
- 基于10%采样点重建完整电压信号
- 插值结果与原始数据长度相同
#### 4. 性能指标计算
```matlab
mse = mean((voltage - reconstructedVoltage).^2);
rmse = sqrt(mse);
mae = mean(abs(voltage - reconstructedVoltage));
r2 = 1 - (ss_res / ss_tot);
```
- MSE:均方误差(衡量总体误差)
- RMSE:均方根误差(与原始数据同单位)
- MAE:平均绝对误差(直观误差大小)
- R²:决定系数(拟合优度,0-1之间)
#### 5. 可视化设计
```matlab
% 原始数据:黑色实线
plot(time, voltage, 'k-', 'LineWidth', 1.5)
% 重建数据:红色实线
plot(time, reconstructedVoltage, 'r-', 'LineWidth', 1.5)
% 误差分布直方图
histogram(error, 50, 'FaceColor', [0.2 0.6 0.8])
```
- 左侧:黑色原始数据 vs 红色重建数据(纯线条,无数据点标记)
- 右侧:误差分布直方图(蓝色系)
- 性能指标以文本框形式显示在右侧图中
#### 6. 数据输出
```matlab
% 输出完整行采样数据
writetable(sampledData, 'sampled_data.xlsx')
% 自动保存图形
saveas(gcf, 'fuel_cell_analysis.png')
```
- 输出包含所有列的采样点数据(不仅仅是电压)
- 自动保存高质量分析图形(PNG格式)
### 关键特性:
1. **样条插值优势**:
- 比线性插值更平滑
- 比多项式插值更稳定
- 特别适合燃料电池电压这类平滑变化的数据
2. **自动化处理**:
- 自动处理图例行
- 自动解决列名不匹配
- 自动计算并显示性能指标
- 自动保存结果文件
3. **可视化优化**:
- 纯线条显示(无数据点标记)
- 专业配色方案
- 清晰的字体和标注
- 紧凑的布局设计
### 使用说明:
1. 确保Excel文件格式:
- 第一行:列标题
- 第二行:图例/单位(将被跳过)
- 第三行开始:实际数据
2. 运行程序后:
- 生成分析图形并自动保存为PNG
- 输出采样数据到`sampled_data.xlsx`
- 控制台显示详细性能指标
3. 如需调整:
- 修改`windowSize`改变信息熵计算窗口
- 修改采样比例(当前0.1→10%)
- 调整图形颜色和样式
阅读全文
相关推荐














