1、文末 有完整两套套实当代码 可直接使用,也可直接通过网盘下载
通过网盘分享的文件链接: https://pan.baidu.com/s/1lY99phZzkjNk1nEY5iRgmw?pwd=sx4d 提取码: sx4d
45页 2.1万字 4800+种模型组合 三种实现方案
题目一提供 3种描述性分析
题目二提供 3种相关性分析+4种因素辨认模型
题目三提供 7种分类模型进行对比(七选二,七选三,七选四,选五、选六等119种可能性)
一共提供 3*3*4*119=4284种。
基于机器学习的新能源电动汽车故障
预警模型研究
摘要
随着全球对环保和能源转型的日益关注,新能源电动汽车(EV)已成为未来出行的主流选择。本文结合新能源电动汽车的行驶数据,采用多种数据处理和机器学习算法,构建了一个电动汽车故障预警模型。
对于题目一,数据预处理及充电和用车规律分析。进行数据合并后,对缺失值进行处理。对于异常值,起首使用sw检验判定正态分布,得出数据分布均为非正态分布。因此起首使用箱线图判定异常值。对于判定出的异常值结合给出数据的实际取值范围进行二次人为异常值判定。统计 1-9 月期间,每个月故障报警次数,并用 折线图 展示报警次数的变化趋势根据充电状态和车辆状态,分析车主的 充电频率、行驶规律,使用 柱状图 和 饼图 展示不同充电和用车状态的占比。
对于题目二, 影响电动汽车故障报警的因素分析。起首使用Spearman相关系数以及卡方检验判定 检查电动汽车的各类数据(车辆数据、电机数据、电池数据)之间的相关性。。为了进一步验证判定效果,分别使用了随机森林、 Lasso回归、 XGBoost、决策树进行辨认特性。最终辨认出分类指标 '车辆状态', '充电状态', 'DC-DC状态' 连续指标 '累计里程', '驱动电机控制器温度'。
对于题目三,电动汽车故障预警模型构建。基于题目二选择的相关特性,分别使用 随机森林、XGBoost、决策树、KNN、LightGBM、 CatBoost和 支持向量机(SVM)进行分类判定。最终综合对比准确率、准确度,召回率,F1-score 等指标。最终选择出最优模型为随机森林。
对于题目四,第10个月故障报警猜测。使用题目一相同的数据处理方式后,选择随机森林模型进行分类判定。最后,结合充电、故障检验和用车规律等方面的分析,给出了该电动汽车的使用建议,旨在资助车主进步车辆的安全性与可靠性。
通过以上方法,本文创建了一个高效、可靠的电动汽车故障预警模型,可以或许有用猜测电动汽车的故障报警,并提供针对性的使用建议,为电动汽车的维护和管理提供了重要的理论和实践支持。
关键词:新能源电动汽车、故障预警、数据预处理、异常值检测、Spearman相关系数、卡方检验、特性选择、随机森林、XGBoost、CatBoost、支持向量机(SVM)、充电规律、用车规律、故障报警猜测
一、题目分析
2.1 题目一分析
数据预处理包括缺失值处理和异常值辨认。具体步调如下:
处理缺失值:对于数值型特性,采用 均值添补 方法。这是由于在许多实际数据集中,部分特性的缺失是不可制止的,使用均值添补可以保证数据的完整性,同时对模型影响较小。
2.4 题目四分析
数据预处理与模型输入:对第 10 个月的数据进行与训练集相同的数据预处理(标签编码、缺失值添补等)。使用训练好的模型对第 10 个月的每一条数据进行故障报警等级猜测。
猜测效果保存与展示:将猜测效果(故障报警时刻和报警等级)保存到 CSV文件 中,并展示在陈诉中。
综上所述,本文研究方案具体如下所示
5.1.3 异常值处理
提取数值型列通过筛选数据集中所有数据范例为数值型的列,对每一列进行正态性检验。
Shapiro-Wilk 检验
对于每个数值型列,利用 Shapiro-Wilk 检验来测试数据是否服从正态分布。
原假设:数据服从正态分布。
检验指标: p 值 。
判定准则:假如 p>0.05(通常采用 5%明显性水平),则不能拒绝原假设,认为数据呈正态分布;否则,认为数据不服从正态分布。
正态分布的列: []
非正态分布的列: ['车辆状态', '充电状态', '车速', '累计里程', '总电压', '总电流', 'SOC', 'DC-DC状态', '绝缘电阻', '驱动电机控制器温度', '驱动电机转速', '驱动电机转矩', '驱动电机温度', '电机控制器输入电压', '电机控制器直流母线电流', '电池单体电压最高值', '电池单体电压最低值', '最高温度值', '最低温度值', '最高报警等级']
对非正态分布列采用箱线图(IQR)方法
在上述异常值检测之外,还对部分关键列进行了额外的数据清洗,通过设定具体数值阈值剔除明显不合理的数据行。具体说明如下
各指标取值区间
| 字段名称
| 说明
| 车速
| 有用值范围:0~2200,最小计量单元:0.1km/h,
| 累计里程
| 有用值范围:0~9999999,最小计量单元:0.1km。
| 总电压
| 有用值范围: 0~10000,最小计量单元: 0.1V
| 总电流
| 有用值范围: 0~20000,最小计量单元: 0.1A
| SOC
| 有用值范围:0~100,最小计量单元:1%
| DC-DC状态
| 1: 工作; 2:断开
| 绝缘电阻
| 有用范围 0~60000,最小计量单元: 1KΩ
| 驱动电机控制器温度
| 有用值范围:0~250,最小计量单元:1℃
| 驱动电机转速
| 偏移量 1000rpm,表现-1000rpm~10000rpm
| 驱动电机温度
| 有用值范围:0~250,最小计量单元:1℃
| 电机控制器输入电压
| 有用值范围: 0~10000,最小计量单元: 0.1V
| 电机控制器直流母线电流
| 有用值范围: 0~20000,最小计量单元: 0.1A
| 电池单体电压最高值
| 有用值范围:0~15 000,最小计量单元:0.001V
| 电池单体电压最低值
| 有用值范围:0~15 000,最小计量单元:0.001V
| 最高温度值
| 有用值范围:0~250,最小计量单元:1℃
| 最低温度值
| 有用值范围:0~250,最小计量单元:1℃
|
可以看到折线在二月和三月之间略有上升,从大约6200上升到6400左右,四月到达全程最高值,约在6500至6600之间。随后五月出现一次明显的下降,报警次数降到大约5400;六月又迅速回升到接近6500的水平,接着七月有所回落到约6300,八月进一步降至5900左右,最后在九月时再次出现较大幅度的下滑,降到约4800附近。整体而言,该折线呈颠簸走势,在四月与六月左右到达峰值,而五月和九月的数值相对较低,显示出月度故障报警次数在春夏日间履历了较大幅度的起伏,进入秋季后则呈下行趋势。
5.2.1 相关性分析-皮尔逊相关性
对于不同的相关性分析方式使用的数据范例不同
Spearman等级相关系数(用于分类数据和连续数据之间的关系)
卡方检验(Chi-Square Test)(用于分类数据之间的关系)
名称
| 数据范例
| 名称
| 车辆状态
| 分类数据
| 驱动电机转速
| 充电状态
| 分类数据
| 驱动电机转矩
| 车速
| 连续数据
| 驱动电机温度
| 累计里程
| 连续数据
| 电机控制器输入电压
| 总电压
| 连续数据
| 电机控制器直流母线电流
| 总电流
| 连续数据
| 电池单体电压最高值
| SOC
| 连续数据
| 电池单体电压最低值
| DC-DC状态
| 分类数据
| 最高温度值
| 绝缘电阻
| 连续数据
| 最低温度值
| 驱动电机控制器温度
| 连续数据
| 最高报警等级
|
主对角线上的数值均为 1,表现特性与自身的完全相关。颜色从深蓝到深红分别表现负相关到正相关,越接近赤色说明正相关水平越强,越接近蓝色则说明负相关越明显,接近白色或浅色则表现相关系数接近零。每个单元格中央的数字为该对特性的具体相关系数,数值范围在 -1 到 1 之间。通过观察颜色和数值,可以快速发现哪些特性之间存在明显的正或负线性关系,如一些相邻或物理意义相近的变量(如总电压与电池单体电压最高值、最低值)每每呈较强正相关;而彼此差异较大的变量(如温度相关特性与转速或电压)可能相关度较弱或呈负相关。整体上,该图资助我们辨认特性间的重要线性依赖关系,为后续的数据建模或降维分析提供参考。
MATLAB 代码
- % 指定包含CSV文件的文件夹路径
- folder_path = 'C:\Users\24404\Desktop\matlab代码\附件';
- % 要合并的文件名列表
- file_names = {'month_01.csv', 'month_02.csv', 'month_03.csv', 'month_04.csv', ...
- 'month_05.csv', 'month_06.csv', 'month_07.csv', 'month_08.csv', 'month_09.csv'};
- % 创建一个空cell数组,用于存储每个CSV文件的数据
- data = {};
- % 遍历每个文件,读取它并将其添加到cell数组中
- for i = 1:length(file_names)
- file_path = fullfile(folder_path, file_names{i}); % 获取完整的文件路径
- try
- % 尝试使用默认编码读取CSV文件
- current_data = readtable(file_path, 'PreserveVariableNames', true);
- catch
- % 如果读取失败,尝试使用另一种编码
- current_data = readtable(file_path, 'PreserveVariableNames', true, 'FileEncoding', 'GBK');
- end
- data{end+1} = current_data; % 将读取的数据添加到cell数组中
- end
- % 合并所有的数据表
- merged_data = vertcat(data{:});
- % 可选:将合并后的数据表保存为新的CSV文件
- writetable(merged_data, fullfile(folder_path, 'merged_data.csv'));
- % 读取已经合并的CSV文件
- merged_file_path = 'C:\Users\24404\Desktop\matlab代码\附件\merged_data.csv';
- % 读取合并后的文件
- merged_data = readtable(merged_file_path);
- % 获取数据框的行数
- num_rows = height(merged_data);
- % 输出总行数
- fprintf('合并后的文件共有 %d 行。\n', num_rows);
- % 删除第 11 至 16 列中包含 "1:" 的部分
- columns_to_process = merged_data(:, 11:16); % 第 11 至第 16 列
- % 对指定列进行处理,删除 "1:" 部分
- for i = 1:width(columns_to_process)
- current_column = columns_to_process{:, i}; % 获取当前列的数据
- current_column = cellfun(@(x) strrep(num2str(x), '1:', ''), current_column, 'UniformOutput', false); % 删除 "1:"
- merged_data{:, 10 + i} = current_column; % 更新到原数据中
- end
- % 输出最后一行的数据
- last_row = merged_data(end, :);
- % 输出最后一行具体数据
- disp('\n最后一行的数据:');
- disp(last_row);
- % 可选:将处理后的数据保存为新的CSV文件
- writetable(merged_data, 'C:\Users\24404\Desktop\matlab代码\附件\processed_merged_data.csv');
- % 读取已经合并的CSV文件
- merged_file_path = 'C:\Users\24404\Desktop\matlab代码\附件\processed_merged_data.csv';
- % 读取合并后的文件
- merged_data = readtable(merged_file_path);
- % 统计缺失值的个数
- missing_values_count = sum(ismissing(merged_data));
- % 输出每列的缺失值个数
- disp('每列的缺失值统计:');
- disp(missing_values_count);
- % 可视化缺失值统计
- figure;
- bar(missing_values_count);
- title('每列缺失值个数');
- xlabel('列名');
- ylabel('缺失值个数');
- % 填充列名为 '驱动电机控制器温度'、'驱动电机转速'、'驱动电机转矩' 等的缺失值为 0
- columns_to_fill_zero = {
- 'x_________', 'x_______1', 'x_______2', 'x_______3', ...
- 'x__________1', 'x___________'
- }; % 根据实际列名修改
- for i = 1:length(columns_to_fill_zero)
- merged_data.(columns_to_fill_zero{i})(ismissing(merged_data.(columns_to_fill_zero{i}))) = 0;
- end
- % 使用上一行数据填充其余缺失值
- merged_data = fillmissing(merged_data, 'previous');
- % 正态分布和非正态分布列
- normal_columns = {};
- non_normal_columns = {};
- % 3西格玛原则:对于正态分布的列,判定异常值
- for col = merged_data.Properties.VariableNames
- col_data = merged_data.(col{1});
- if isnumeric(col_data) && isvector(col_data)
- % 使用拟合正态分布进行正态性检验
- try
- pd = fitdist(col_data(~isnan(col_data)), 'Normal'); % 拟合正态分布
- [~, p_value] = chi2gof(col_data(~isnan(col_data)), 'CDF', pd); % 卡方检验
- if p_value > 0.05
- normal_columns{end+1} = col{1}; % 正态分布列
- else
- non_normal_columns{end+1} = col{1}; % 非正态分布列
- end
- catch
- non_normal_columns{end+1} = col{1}; % 如果拟合失败,默认认为是非正态分布
- end
- end
- end
- % 输出正态分布和非正态分布的列
- disp('正态分布的列:');
- disp(normal_columns);
- disp('非正态分布的列:');
- disp(non_normal_columns);
- % 3西格玛原则:检测正态分布的列的异常值
- for col = normal_columns
- col_data = merged_data.(col{1});
- mean_val = mean(col_data, 'omitnan');
- std_dev = std(col_data, 'omitnan');
- threshold = 3; % 设置为3西格玛原则
- upper_bound = mean_val + threshold * std_dev;
- lower_bound = mean_val - threshold * std_dev;
- % 找到异常值
- outliers = merged_data(col_data < lower_bound | col_data > upper_bound, :);
- % 可视化异常值
- figure;
- boxplot(col_data);
- title([col{1}, ' 列异常值检测(3西格玛原则)']);
- disp([col{1}, ' 列的异常值数量: ', num2str(height(outliers))]);
- end
- % 对于非正态分布的列,使用箱线图判定异常值
- for col = non_normal_columns
- col_data = merged_data.(col{1});
- figure;
- boxplot(col_data);
- title([col{1}, ' 列异常值检测(箱线图)']);
- % 删除 NaN 值后计算分位数
- non_nan_data = col_data(~isnan(col_data));
- Q1 = quantile(non_nan_data, 0.25);
- Q3 = quantile(non_nan_data, 0.75);
- IQR = Q3 - Q1;
- lower_bound = Q1 - 1.5 * IQR;
- upper_bound = Q3 + 1.5 * IQR;
- outliers = merged_data(col_data < lower_bound | col_data > upper_bound, :);
- disp([col{1}, ' 列的异常值数量: ', num2str(height(outliers))]);
- end
- merged_data.Properties.VariableNames = {...
- '数据采集时间', '车辆状态', '充电状态', '车速', '累计里程', '总电压', '总电流', 'SOC', ...
- 'DC-DC状态', '绝缘电阻', '驱动电机控制器温度', '驱动电机转速', '驱动电机转矩', '驱动电机温度', ...
- '电机控制器输入电压', '电机控制器直流母线电流', '电池单体电压最高值', '电池单体电压最低值', ...
- '最高温度值', '最低温度值', '最高报警等级'};
- % 可选:将处理后的数据保存为新的CSV文件
- writetable(merged_data, 'C:\Users\24404\Desktop\matlab代码\附件\processed_merged_data1.csv');
- clc;
- clear;
- %% 自定义“coolwarm” colormap(仅为近似效果)
- n = 256;
- % 简单构造一个从蓝色(低值)过渡到白色,再到红色(高值)的 colormap
- r = [linspace(0, 1, n/2)'; ones(n/2,1)];
- g = [linspace(0, 1, n/2)'; linspace(1, 0, n/2)'];
- b = [ones(n/2,1); linspace(1, 0, n/2)'];
- coolwarm = [r, g, b];
- %% ======================= Part 1: 特征相关性矩阵 =======================
- % 加载数据
- file_path = 'C:\Users\24404\Desktop\matlab代码\附件\processed_merged_data1_cleaned.csv';
- opts = detectImportOptions(file_path, 'VariableNamingRule', 'preserve');
- data = readtable(file_path, opts);
- % 数据预处理:确保日期格式(后续分析可能需要)
- data.('数据采集时间') = datetime(data.('数据采集时间'));
- % 将报警等级转换(本部分只用于连续变量相关性计算,不影响后续)
- data.('报警等级') = data.('最高报警等级');
- % 定义特征列表
- features = {'车速','累计里程','总电压','总电流','SOC','DC-DC状态','绝缘电阻',...
- '驱动电机控制器温度','驱动电机转速','驱动电机转矩','驱动电机温度',...
- '电机控制器输入电压','电机控制器直流母线电流','电池单体电压最高值',...
- '电池单体电压最低值','最高温度值','最低温度值'};
- % 提取特征数据,并转换为数值矩阵(假设这些列均为数值型)
- X = data(:, features);
- X_mat = table2array(X);
- % 计算皮尔逊相关性矩阵(对缺失值使用 pairwise 计算)
- corrMatrix = corr(X_mat, 'Rows', 'pairwise');
- % 绘制相关性矩阵热力图
- figure('Position',[100,100,800,600]);
- h1 = heatmap(features, features, corrMatrix, 'CellLabelFormat','%.2f');
- h1.Title = '特征相关性矩阵';
- % 设置自定义 colormap
- h1.Colormap = coolwarm;
- h1.ColorbarVisible = 'on';
- % 输出相关性矩阵
- disp('特征相关性矩阵:');
- disp(corrMatrix);
- %% ======================= Part 2: Spearman等级相关系数分析 =======================
- % 将报警等级映射为数值(假设原始“最高报警等级”为 0,1,2,3)
- % 这里将 '无故障' 映射为 0,'1级故障' 为 1,以此类推
- data.('报警等级') = double( data.('最高报警等级') );
- % 对每个连续特征与报警等级计算 Spearman 相关系数
- spearmanCorr = zeros(length(features),1);
- for i = 1:length(features)
- % 取出当前特征数据,确保为数值型
- featureData = data.(features{i});
- if ~isnumeric(featureData)
- featureData = str2double(featureData);
- end
- % 计算 Spearman 等级相关系数(忽略 NaN)
- spearmanCorr(i) = corr(featureData, data.('报警等级'), 'Type', 'Spearman', 'Rows','pairwise');
- end
- % 绘制 Spearman 相关系数热力图(单行热图)
- figure('Position',[100,100,800,200]);
- h2 = heatmap(features, {'报警等级'}, spearmanCorr');
- h2.Title = 'Spearman等级相关系数:连续数据与报警等级之间的相关性';
- h2.Colormap = coolwarm;
- h2.CellLabelFormat = '%.2f';
- % 输出 Spearman 相关系数
- disp('Spearman等级相关系数:');
- T_spearman = array2table(spearmanCorr, 'RowNames', features, 'VariableNames', {'SpearmanCorr'});
- disp(T_spearman);
- %% 加载数据
- file_path = 'C:\Users\24404\Desktop\matlab代码\附件\processed_merged_data1_cleaned.csv';
- opts = detectImportOptions(file_path, 'VariableNamingRule', 'preserve');
- data = readtable(file_path, opts);
- %% 数据预处理
- % 1. 将“数据采集时间”转换为日期格式后删除该列
- data.('数据采集时间') = datetime(data.('数据采集时间'));
- data.('数据采集时间') = [];
- % 2. 对分类数据进行标签编码: '车辆状态', '充电状态', 'DC-DC状态'
- categorical_features = {'车辆状态', '充电状态', 'DC-DC状态'};
- for i = 1:length(categorical_features)
- feat = categorical_features{i};
- data.(feat) = grp2idx(categorical(data.(feat)));
- end
- % 3. 处理缺失值:使用均值填充数值型特征
- numerical_features = {...
- '车速', '累计里程', '总电压', '总电流', 'SOC', '绝缘电阻',...
- '驱动电机控制器温度', '驱动电机转速', '驱动电机转矩', '驱动电机温度',...
- '电机控制器输入电压', '电机控制器直流母线电流', '电池单体电压最高值',...
- '电池单体电压最低值', '最高温度值', '最低温度值'};
- for i = 1:length(numerical_features)
- col = numerical_features{i};
- colData = data.(col);
- meanVal = mean(colData, 'omitnan');
- data.(col) = fillmissing(colData, 'constant', meanVal);
- end
- %% 选择特征和目标变量
- features = {'车辆状态', '充电状态', 'DC-DC状态', '累计里程', '驱动电机控制器温度', '最高温度值'};
- X = data(:, features);
- y = data.('最高报警等级');
- %% 拆分数据集(80% 训练,20% 测试)
- nSamples = height(data);
- cv = cvpartition(nSamples, 'HoldOut', 0.2);
- trainIdx = training(cv);
- testIdx = test(cv);
- X_train = X(trainIdx, :);
- y_train = y(trainIdx);
- X_test = X(testIdx, :);
- y_test = y(testIdx);
- %% KNN模型训练(邻居数设置为5)
- model_knn = fitcknn(X_train, y_train, 'NumNeighbors', 5);
- %% 预测
- y_pred = predict(model_knn, X_test);
- %% 模型评估
- % 计算混淆矩阵
- cm = confusionmat(y_test, y_pred);
- % 计算准确率
- accuracy = sum(diag(cm)) / sum(cm(:));
- % 计算每个类别的精确率、召回率和F1-score
- classes = unique(y_test);
- nClasses = numel(classes);
- precision = zeros(nClasses, 1);
- recall = zeros(nClasses, 1);
- f1 = zeros(nClasses, 1);
- for i = 1:nClasses
- TP = cm(i,i);
- FP = sum(cm(:,i)) - TP;
- FN = sum(cm(i,:)) - TP;
- precision(i) = TP / (TP + FP + eps);
- recall(i) = TP / (TP + FN + eps);
- f1(i) = 2 * precision(i) * recall(i) / (precision(i) + recall(i) + eps);
- end
- macro_recall = mean(recall);
- macro_f1 = mean(f1);
- % 输出分类报告
- fprintf('KNN 分类报告:\n');
- fprintf('准确率: %.4f\n', accuracy);
- fprintf('宏平均召回率: %.4f\n', macro_recall);
- fprintf('宏平均 F1-score: %.4f\n', macro_f1);
- disp('混淆矩阵:');
- disp(cm);
- %% 绘制模型评估指标柱状图
- metrics = [accuracy, macro_recall, macro_f1];
- metric_names = {'准确率','召回率','F1-score'};
- figure('Position', [100, 100, 600, 400]);
- bar(categorical(metric_names), metrics);
- title('KNN 模型评估指标', 'FontSize', 14);
- xlabel('指标', 'FontSize', 12);
- ylabel('得分', 'FontSize', 12);
- grid on;
复制代码 PYTHON代码
- import pandas as pd
- import os
- # 指定包含CSV文件的文件夹路径
- folder_path = r'C:\Users\24404\PycharmProjects\pythonProject1\未来杯\附件'
- # 要合并的文件名列表
- file_names = ['month_01.csv', 'month_02.csv', 'month_03.csv', 'month_04.csv',
- 'month_05.csv', 'month_06.csv', 'month_07.csv', 'month_08.csv', 'month_09.csv']
- # 创建一个空列表,用于存储每个CSV文件的DataFrame
- dfs = []
- # 遍历每个文件,读取它并将其添加到列表中
- for file in file_names:
- file_path = os.path.join(folder_path, file) # 获取完整的文件路径
- try:
- df = pd.read_csv(file_path, encoding='utf-8') # 尝试使用utf-8编码读取CSV文件
- except UnicodeDecodeError: # 如果出现解码错误,尝试使用GBK编码
- df = pd.read_csv(file_path, encoding='GBK') # 使用GBK编码读取
- dfs.append(df) # 将DataFrame添加到列表中
- # 使用pd.concat()将所有DataFrame按行合并
- merged_df = pd.concat(dfs, ignore_index=True)
- # 可选:将合并后的DataFrame保存为新的CSV文件
- merged_df.to_csv(os.path.join(folder_path, 'merged_data.csv'), index=False)
- import pandas as pd
- # 读取已经合并的CSV文件
- merged_file_path = r'C:\Users\24404\PycharmProjects\pythonProject1\未来杯\附件\merged_data.csv'
- # 读取合并后的文件
- merged_df = pd.read_csv(merged_file_path)
- # 获取数据框的行数
- num_rows = len(merged_df)
- # 输出总行数
- print(f"合并后的文件共有 {num_rows} 行。")
- # 删除第 11 至 16 列中包含 "1:" 的部分
- columns_to_process = merged_df.columns[10:16] # 第 11 至第 16 列对应的列名(索引从 0 开始,所以是 10 到 15)
- # 对指定列进行处理,删除 "1:" 部分
- for col in columns_to_process:
- merged_df[col] = merged_df[col].apply(lambda x: str(x).replace("1:", "") if isinstance(x, str) else x)
- # 输出最后一行的数据
- last_row = merged_df.iloc[-1]
- # 输出最后一行具体数据
- print("\n最后一行的数据:")
- print(last_row)
- # 可选:将处理后的数据保存为新的CSV文件
- merged_df.to_csv(r'C:\Users\24404\PycharmProjects\pythonProject1\未来杯\附件\processed_merged_data.csv', index=False)
- plt.rcParams['font.sans-serif'] = ['SimHei'] # 使用SimHei字体
- plt.rcParams['axes.unicode_minus'] = False # 正确显示负号
- # 读取已经合并的CSV文件
- merged_file_path = r'C:\Users\24404\PycharmProjects\pythonProject1\未来杯\附件\processed_merged_data.csv'
- # 读取合并后的文件
- merged_df = pd.read_csv(merged_file_path)
- # 统计缺失值的个数
- missing_values_count = merged_df.isnull().sum()
- # 输出每列的缺失值个数
- print("每列的缺失值统计:")
- print(missing_values_count)
- # 可视化缺失值统计
- plt.figure(figsize=(10, 6))
- missing_values_count.plot(kind='bar')
- plt.title("每列缺失值个数")
- plt.xlabel('列名')
- plt.ylabel('缺失值个数')
- plt.xticks(rotation=90)
- plt.show()
- print(merged_df.columns)
- # 填充列名为 '驱动电机控制器温度'、'驱动电机转速'、'驱动电机转矩' 等的缺失值为 0
- columns_to_fill_zero = [
- '驱动电机控制器温度', '驱动电机转速', '驱动电机转矩', '驱动电机温度', '电机控制器输入电压', '电机控制器直流母线电流'
- ] # 根据实际列名修改
- merged_df[columns_to_fill_zero] = merged_df[columns_to_fill_zero].fillna(0)
- # 使用上一行数据填充其余缺失值
- merged_df.fillna(method='ffill', inplace=True)
- # 正态分布和非正态分布列
- normal_columns = []
- non_normal_columns = []
- # 3西格玛原则:对于正态分布的列,判定异常值
- for col in merged_df.select_dtypes(include=[np.number]).columns:
- # 使用Shapiro-Wilk检验检测正态性
- _, p_value = stats.shapiro(merged_df[col].dropna()) # 去除空值进行检验
- if p_value > 0.05:
- normal_columns.append(col)
- else:
- non_normal_columns.append(col)
- # 输出正态分布和非正态分布的列
- print(f"\n正态分布的列: {normal_columns}")
- print(f"非正态分布的列: {non_normal_columns}")
- # 3西格玛原则:检测正态分布的列的异常值
- for col in normal_columns:
- mean = merged_df[col].mean()
- std_dev = merged_df[col].std()
- threshold = 3 # 设置为3西格玛原则
- upper_bound = mean + threshold * std_dev
- lower_bound = mean - threshold * std_dev
- # 找到异常值
- outliers = merged_df[(merged_df[col] < lower_bound) | (merged_df[col] > upper_bound)]
- # 可视化异常值
- plt.figure(figsize=(10, 6))
- plt.title(f"{col} 列异常值检测(3西格玛原则)")
- sns.boxplot(x=merged_df[col])
- plt.show()
- print(f"{col} 列的异常值数量: {len(outliers)}")
- # 对于非正态分布的列,使用箱线图判定异常值
- for col in non_normal_columns:
- plt.figure(figsize=(10, 6))
- plt.title(f"{col} 列异常值检测(箱线图)")
- sns.boxplot(x=merged_df[col])
- plt.show()
- # 找到异常值
- Q1 = merged_df[col].quantile(0.25)
- Q3 = merged_df[col].quantile(0.75)
- IQR = Q3 - Q1
- lower_bound = Q1 - 1.5 * IQR
- upper_bound = Q3 + 1.5 * IQR
- outliers = merged_df[(merged_df[col] < lower_bound) | (merged_df[col] > upper_bound)]
- print(f"{col} 列的异常值数量: {len(outliers)}")
- # 可选:将处理后的数据保存为新的CSV文件
- merged_df.to_csv(r'C:\Users\24404\PycharmProjects\pythonProject1\未来杯\附件\processed_merged_data1.csv', index=False)
- plt.rcParams['font.sans-serif'] = ['SimHei'] # 使用SimHei字体
- plt.rcParams['axes.unicode_minus'] = False # 正确显示负号
- # 读取已经合并的CSV文件
- # 文件路径(每个月的数据文件),这里假设数据文件有一个通用格式,如 'month_01.csv', 'month_02.csv' 等
- folder_path = r'C:\Users\24404\PycharmProjects\pythonProject1\未来杯\附件'
- # 创建一个文件名列表,包含01月到09月的文件
- file_names = [f'month_{i:02d}.csv' for i in range(1, 10)] # 格式化为 month_01, month_02, ..., month_09
- # 创建一个空的DataFrame,合并所有文件的数据
- dfs = []
- for file in file_names:
- file_path = f'{folder_path}\\{file}'
- try:
- # 尝试用utf-8编码读取
- df = pd.read_csv(file_path, encoding='utf-8')
- except UnicodeDecodeError:
- # 如果遇到编码错误,尝试使用GBK编码
- df = pd.read_csv(file_path, encoding='GBK')
- dfs.append(df)
- # 合并所有的DataFrame
- merged_df = pd.concat(dfs, ignore_index=True)
- # 将 "数据采集时间" 列转换为 datetime 格式
- merged_df['数据采集时间'] = pd.to_datetime(merged_df['数据采集时间'], errors='coerce')
- # 提取月份信息,添加到一个新的列 'month'
- merged_df['month'] = merged_df['数据采集时间'].dt.month
- # 统计每月的故障报警次数(假设 "最高报警等级" 表示故障报警,若需修改请根据实际列名调整)
- monthly_fault_alarms = merged_df.groupby('month')['最高报警等级'].count()
- # 可视化故障报警次数
- plt.figure(figsize=(10, 6))
- sns.lineplot(x=monthly_fault_alarms.index, y=monthly_fault_alarms.values, marker='o')
- plt.title('每月故障报警次数及其变化规律')
- plt.xlabel('月份')
- plt.ylabel('故障报警次数')
- plt.grid(True)
- plt.show()
- # 2. 统计每月的充电情况
- # 假设 "充电状态" 列表示充电状态,统计充电状态为"充电中"的次数
- monthly_charge_count = merged_df[merged_df['充电状态'] == '充电中'].groupby('month').size()
- # 可视化充电次数
- plt.figure(figsize=(10, 6))
- sns.barplot(x=monthly_charge_count.index, y=monthly_charge_count.values)
- plt.title('每月充电次数')
- plt.xlabel('月份')
- plt.ylabel('充电次数')
- plt.show()
- # 3. 统计每月的用车情况
- # 假设 "车速" 列表示用车数据,用车次数可以通过车速不为零的记录进行计算
- monthly_drive_count = merged_df[merged_df['车速'] > 0].groupby('month').size()
- # 可视化用车次数
- plt.figure(figsize=(10, 6))
- sns.barplot(x=monthly_drive_count.index, y=monthly_drive_count.values)
- plt.title('每月用车次数')
- plt.xlabel('月份')
- plt.ylabel('用车次数')
- plt.show()
- # 4. 总结分析
- print("故障报警次数每月变化:")
- print(monthly_fault_alarms)
- print("\n每月充电情况:")
- print(f"充电次数:\n{monthly_charge_count}")
- print("\n每月用车情况:")
- print(f"用车次数:\n{monthly_drive_count}")
- file_path = r'C:\Users\24404\PycharmProjects\pythonProject1\未来杯\附件\processed_merged_data1_cleaned.csv'
- data = pd.read_csv(file_path)
- # 数据预处理
- # 1. 删除 "数据采集时间" 列(或转换为数值型)
- data['数据采集时间'] = pd.to_datetime(data['数据采集时间'])
- data.drop('数据采集时间', axis=1, inplace=True) # 删除“数据采集时间”列
- # 2. 对分类数据进行标签编码
- categorical_features = ['车辆状态', '充电状态', 'DC-DC状态']
- le = LabelEncoder()
- for feature in categorical_features:
- data[feature] = le.fit_transform(data[feature].astype(str))
- # 3. 处理缺失值
- # 使用SimpleImputer对数值型特征进行缺失值填充
- numerical_features = [
- '车速', '累计里程', '总电压', '总电流', 'SOC', '绝缘电阻',
- '驱动电机控制器温度', '驱动电机转速', '驱动电机转矩', '驱动电机温度',
- '电机控制器输入电压', '电机控制器直流母线电流', '电池单体电压最高值',
- '电池单体电压最低值', '最高温度值', '最低温度值'
- ]
- # 填充缺失值
- from sklearn.impute import SimpleImputer
- imputer = SimpleImputer(strategy='mean') # 用均值填充
- data[numerical_features] = imputer.fit_transform(data[numerical_features])
- # 选择特征和目标变量
- features = ['车辆状态', '充电状态', 'DC-DC状态', '累计里程', '驱动电机控制器温度', '最高温度值']
- X = data[features]
- y = data['最高报警等级']
- # 拆分数据集
- X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42)
- # KNN模型
- knn = KNeighborsClassifier(n_neighbors=5)
- knn.fit(X_train, y_train)
- # 预测并评估
- y_pred_knn = knn.predict(X_test)
- # 输出分类报告
- print("KNN分类报告:")
- print(classification_report(y_test, y_pred_knn))
- # 计算模型的评估指标
- accuracy_knn = accuracy_score(y_test, y_pred_knn)
- report_knn = classification_report(y_test, y_pred_knn, output_dict=True)
- # 提取精确度、召回率和F1-score
- metrics_knn = {
- '精确度': report_knn['accuracy'],
- '召回率': report_knn['macro avg']['recall'],
- 'F1-score': report_knn['macro avg']['f1-score']
- }
- # 绘制可视化结果
- plt.figure(figsize=(8, 6))
- sns.barplot(x=list(metrics_knn.keys()), y=list(metrics_knn.values()))
- plt.title('KNN模型评估指标')
- plt.ylabel('得分')
- plt.xlabel('指标')
- plt.tight_layout()
- plt.show()
复制代码
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。
|