机器学习——集成学习、线性模型、支持向量机、K近邻、决策树、朴素贝叶斯、虚拟分类器分析电动车数据集Python完整代码
背景
🌍 数据集描述
该数据集提供了有关各个地区和时期电动车(EV)人口的全面信息。它包括与车辆注册、清洁替代燃料车辆项目的资格以及电动范围和定价相关的各种测量数据。数据覆盖了多个州和车辆品牌,为电动车市场及其发展提供了广泛的视角。
📊 列说明:
-
州:车辆注册所在的美国州。
-
车型年份:车辆型号的制造年份。
-
品牌:车辆的制造商,例如:
-
特斯拉(TESLA)
-
宝马(BMW)
-
雪佛兰(CHEVROLET)
-
大众(VOLKSWAGEN)
-
瑞维安(RIVIAN)
-
丰田(TOYOTA)
-
日产(NISSAN)
-
…(还有更多)
-
-
电动车类型:电动车的类型,分类为:
-
电池电动车(BEV)
-
插电式混合电动车(PHEV)
-
-
电动范围:车辆仅靠电力驱动时的续航里程,以英里为单位。
-
基础建议零售价(Base MSRP):车辆的制造商建议零售价(MSRP)。
-
立法区:与车辆注册地点相关的立法区。
-
CAFV资格简单指示:车辆是否符合清洁替代燃料车辆(CAFV)项目资格的简化指示。可能的值包括:
-
符合清洁替代燃料车辆资格
-
由于未研究电池续航,资格未知
-
由于低电池续航,不符合资格
-
🔍 使用案例:
该数据集非常适合分析不同州电动车的采用和分布,强调地理和立法细节。它对于理解电动车市场的趋势、评估定价和评估替代燃料车辆激励措施的可及性非常有用。该数据集还可用于预测建模,帮助根据地理、人口和立法因素预测电动车的增长和传播。
1. 导入必要的库
import numpy as np # 用于数值计算,如数组操作、数学运算等
import matplotlib.pyplot as plt # 用于绘制静态图表
import seaborn as sns # 基于matplotlib的高级数据可视化库
import pandas as pd # 用于数据处理和分析
import plotly.express as px # 用于绘制交互式图表
import warnings # 用于处理警告信息
warnings.filterwarnings('ignore') # 忽略所有警告信息,避免干扰输出
# 从sklearn库中导入模型选择、集成学习、线性模型、支持向量机、K近邻、决策树、朴素贝叶斯、虚拟分类器等模块
from sklearn.model_selection import train_test_split, cross_val_score # 数据集划分和交叉验证
from sklearn.ensemble import RandomForestClassifier, GradientBoostingClassifier, AdaBoostClassifier, VotingClassifier # 集成学习模型
from sklearn.linear_model import LogisticRegression # 逻辑回归模型
from sklearn.svm import SVC # 支持向量机分类器
from sklearn.neighbors import KNeighborsClassifier # K近邻分类器
from sklearn.tree import DecisionTreeClassifier # 决策树分类器
from sklearn.naive_bayes import GaussianNB # 高斯朴素贝叶斯分类器
from sklearn.dummy import DummyClassifier # 虚拟分类器,用于基准测试
from sklearn.metrics import accuracy_score, precision_score, recall_score, f1_score, roc_auc_score # 模型评估指标
2. 数据加载与初步探索
# 加载数据集
filepath = r"2025-1-16-公众号python机器学习ML-EV_Population.csv"
df = pd.read_csv(filepath) # 读取CSV文件
df.head() # 显示数据集的前5行,用于初步查看数据
重要参数说明
filepath
:数据文件的路径。
pd.read_csv()
:读取CSV文件并加载为DataFrame。
df.head()
:显示前5行数据,用于快速了解数据结构和内容。
3. 数据预处理
3.1 检查数据形状与缺失值
df.shape # 查看数据集的形状(行数,列数)
df.isnull().sum() # 检查每列的缺失值数量
df.duplicated().sum() # 检查数据集中重复行的数量
3.2 处理重复值
duplicates = df.duplicated(keep=False) # 标记所有重复行,keep=False表示标记所有重复行
df['Is_Duplicate'] = duplicates # 添加一列标记重复行
# 可视化重复值的分布
sns.countplot(data=df, x='Is_Duplicate', palette='coolwarm') # 绘制重复值的分布图
plt.title('Duplicate Rows Count') # 设置标题
plt.xlabel('Is Duplicate') # 设置x轴标签
plt.ylabel('Count') # 设置y轴标签
plt.xticks(ticks=[0, 1], labels=['Unique', 'Duplicate']) # 设置x轴刻度标签
plt.show() # 显示图表
# 删除重复行并保留第一个出现的行
df = df.drop_duplicates(keep='first') # 删除重复行,keep='first'表示保留第一个出现的行
df.reset_index(drop=True, inplace=True) # 重置索引,drop=True表示删除旧索引
重要参数说明
df.duplicated(keep=False)
:标记所有重复行。
sns.countplot()
:绘制分类变量的计数图。
df.drop_duplicates(keep='first')
:删除重复行,保留第一个出现的行。
4. 数据可视化
# 绘制车辆品牌分布
plt.figure(figsize=(8, 5))
sns.countplot(data=df, x="Make", palette="viridis")
plt.title("Count of Vehicles by Make")
plt.xlabel("Make")
plt.ylabel("Count")
plt.xticks(rotation=90)
plt.show()
-
**sns.countplot()**:绘制每个品牌(Make)的车辆数量。
# 绘制电动续航里程分布
plt.figure(figsize=(8, 5))
sns.histplot(data=df, x="Electric Range", kde=True, bins=10, color="blue")
plt.title("Electric Range Distribution")
plt.xlabel("Electric Range (miles)")
plt.ylabel("Frequency")
plt.show()
-
**sns.histplot()**:绘制电动续航里程的分布图,并加上核密度估计(KDE)来显示数据分布。
# 电动车类型分布饼图
df['Electric Vehicle Type'].value_counts().plot.pie(
autopct='%1.1f%%', startangle=90, colors=sns.color_palette("Set2"), figsize=(6, 6)
)
plt.title("Distribution of Electric Vehicle Types")
plt.ylabel("") # 去掉y轴标签
plt.show()
-
**df['Electric Vehicle Type'].value_counts().plot.pie()**:绘制电动车类型的饼图,显示各类型的占比。
# 绘制箱线图,显示每年的电动续航里程分布
plt.figure(figsize=(8, 5))
sns.boxplot(data=df, x="Model Year", y="Electric Range", palette="coolwarm")
plt.title("Electric Range by Model Year")
plt.xlabel("Model Year")
plt.ylabel("Electric Range (miles)")
plt.show()
-
**sns.boxplot()**:绘制箱线图,展示不同年份(Model Year)的电动续航里程分布。
# 绘制小提琴图,展示不同电动车类型的电动续航里程
plt.figure(figsize=(8, 5))
sns.violinplot(data=df, x="Electric Vehicle Type", y="Electric Range", palette="muted")
plt.title("Electric Range by Electric Vehicle Type")
plt.xlabel("Electric Vehicle Type")
plt.ylabel("Electric Range (miles)")
plt.show()
-
**sns.violinplot()**:绘制小提琴图,展示电动车类型对续航里程的影响。
# 绘制散点图,展示电动续航里程与基础价格的关系
plt.figure(figsize=(8, 5))
sns.scatterplot(data=df, x="Base MSRP", y="Electric Range", hue="Make", style="Electric Vehicle Type", palette="deep")
plt.title("Electric Range vs Base MSRP")
plt.xlabel("Base MSRP ($)")
plt.ylabel("Electric Range (miles)")
plt.show()
-
**sns.scatterplot()**:绘制散点图,展示基础价格(Base MSRP)与电动续航里程的关系。
# 绘制趋势线图,展示不同年份电动续航里程的变化趋势
plt.figure(figsize=(8, 5))
sns.lineplot(data=df, x="Model Year", y="Electric Range", marker="o", hue="Make", palette="dark")
plt.title("Trend of Electric Range by Model Year")
plt.xlabel("Model Year")
plt.ylabel("Electric Range (miles)")
plt.show()
-
**sns.lineplot()**:绘制折线图,展示不同年份电动续航里程的变化趋势。
6. 相关性分析
plt.figure(figsize=(8, 5))
corr_matrix = df.corr(numeric_only=True) # 计算数值列的相关性矩阵
sns.heatmap(corr_matrix, annot=True, cmap="coolwarm", fmt=".2f")
plt.title("Correlation Heatmap")
plt.show()
-
**df.corr(numeric_only=True)**:计算数值列之间的相关性矩阵。
-
**sns.heatmap()**:绘制相关性热图,展示各数值特征之间的相关性。
7. 使用Plotly绘制交互式图表
# 交互式条形图:展示不同立法区的电动续航里程
fig = px.bar(
df,
x="Legislative District",
y="Electric Range",
color="Make",
barmode="group",
title="Electric Range by Legislative District",
labels={"Electric Range": "Electric Range (miles)"},
)
fig.show()
-
**px.bar()**:使用Plotly绘制交互式条形图,展示不同立法区的电动续航里程。
# 交互式散点图:展示基础价格与电动续航里程的关系
fig = px.scatter(
df,
x="Base MSRP",
y="Electric Range",
color="Make",
size="Electric Range",
hover_data=["Electric Vehicle Type"],
title="Electric Range vs Base MSRP",
)
fig.show()
-
**px.scatter()**:使用Plotly绘制交互式散点图,展示基础价格与电动续航里程之间的关系。
5. 特征工程
5.1 标签编码
from sklearn.preprocessing import LabelEncoder
label_encoder = LabelEncoder() # 初始化标签编码器
categorical_columns = df.select_dtypes(include=['object']).columns # 识别分类列
# 对每个分类列进行标签编码
for col in categorical_columns:
df[col] = label_encoder.fit_transform(df[col]) # 将分类变量转换为数值
5.2 数据标准化
from sklearn.preprocessing import MinMaxScaler
scaler = MinMaxScaler() # 初始化MinMaxScaler
numerical_columns = df.select_dtypes(include=['int64', 'float64']).columns # 识别数值列
# 对数值列进行标准化
df[numerical_columns] = scaler.fit_transform(df[numerical_columns]) # 将数值列缩放到[0, 1]范围
6. 模型训练与评估
6.1 数据集划分
X = df.drop('Electric Vehicle Type', axis=1) # 特征矩阵,删除目标列
y = df['Electric Vehicle Type'] # 目标变量
# 划分训练集和测试集
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42) # 80%训练集,20%测试集
6.2 定义分类器列表
classifiers = [
('Logistic Regression', LogisticRegression()), # 逻辑回归
('KNN', KNeighborsClassifier()), # K近邻
('Decision Tree', DecisionTreeClassifier()), # 决策树
('Random Forest', RandomForestClassifier()), # 随机森林
('Gradient Boosting', GradientBoostingClassifier()), # 梯度提升
('AdaBoost', AdaBoostClassifier()), # AdaBoost
('Naive Bayes', GaussianNB()), # 朴素贝叶斯
('SVM', SVC(probability=True)), # 支持向量机
('Dummy Classifier', DummyClassifier(strategy='most_frequent')), # 虚拟分类器
('Voting Classifier', VotingClassifier(estimators=[
('lr', LogisticRegression()),
('rf', RandomForestClassifier()),
('svc', SVC(probability=True))
], voting='soft')) # 投票分类器
]
6.3 模型评估
results = {
'Model': [],
'Accuracy': [],
'Precision': [],
'Recall': [],
'F1 Score': [],
'ROC AUC': []
}
for name, clf in classifiers:
cv_score = cross_val_score(clf, X_train, y_train, cv=5, scoring='accuracy') # 交叉验证
clf.fit(X_train, y_train) # 训练模型
y_pred = clf.predict(X_test) # 预测测试集
accuracy = accuracy_score(y_test, y_pred) # 计算准确率
precision = precision_score(y_test, y_pred, average='weighted', zero_division=0) # 计算精确率
recall = recall_score(y_test, y_pred, average='weighted', zero_division=0) # 计算召回率
f1 = f1_score(y_test, y_pred, average='weighted') # 计算F1分数
ifnot is_binary: # 如果是多分类问题
lb = LabelBinarizer()
lb.fit(y)
y_test_bin = lb.transform(y_test)
y_pred_prob = clf.predict_proba(X_test)
roc_auc = roc_auc_score(y_test_bin, y_pred_prob, multi_class='ovr', average='weighted') # 计算ROC AUC
else: # 如果是二分类问题
y_pred_prob = clf.predict_proba(X_test)[:, 1]
roc_auc = roc_auc_score(y_test, y_pred_prob)
results['Model'].append(name)
results['Accuracy'].append(accuracy)
results['Precision'].append(precision)
results['Recall'].append(recall)
results['F1 Score'].append(f1)
results['ROC AUC'].append(roc_auc)
results_df = pd.DataFrame(results) # 将结果转换为DataFrame
print(results_df) # 打印结果
7. 结果可视化
fig, ax = plt.subplots(2, 2, figsize=(14, 10)) # 创建2x2的子图
# 绘制准确率对比图
sns.barplot(x='Accuracy', y='Model', data=results_df, ax=ax[0, 0], palette='viridis')
ax[0, 0].set_title('Accuracy Comparison')
# 绘制精确率对比图
sns.barplot(x='Precision', y='Model', data=results_df, ax=ax[0, 1], palette='viridis')
ax[0, 1].set_title('Precision Comparison')
# 绘制召回率对比图
sns.barplot(x='Recall', y='Model', data=results_df, ax=ax[1, 0], palette='viridis')
ax[1, 0].set_title('Recall Comparison')
# 绘制F1分数对比图
sns.barplot(x='F1 Score', y='Model', data=results_df, ax=ax[1, 1], palette='viridis')
ax[1, 1].set_title('F1 Score Comparison')
plt.tight_layout() # 调整子图间距
plt.show() # 显示图表
8. 混淆矩阵与分类报告
from sklearn.metrics import confusion_matrix, classification_report
clf.fit(X_train, y_train) # 训练模型
y_pred = clf.predict(X_test) # 预测测试集
cm = confusion_matrix(y_test, y_pred) # 计算混淆矩阵
plt.figure(figsize=(8, 6)) # 设置图表大小
sns.heatmap(cm, annot=True, fmt='d', cmap='Blues', xticklabels=clf.classes_, yticklabels=clf.classes_) # 绘制混淆矩阵热图
plt.title('Confusion Matrix') # 设置标题
plt.xlabel('Predicted Labels') # 设置x轴标签
plt.ylabel('True Labels') # 设置y轴标签
plt.show() # 显示图表
print(classification_report(y_test, y_pred)) # 打印分类报告
本文详细讲解了如何使用Python进行电动车数据集的加载、处理、可视化与分析。在数据预处理阶段,我们通过处理重复数据和缺失值,确保数据的质量。在数据可视化部分,我们展示了多种图表,如直方图、箱线图、散点图等,帮助我们更好地理解数据的分布和趋势。同时,我们还通过交互式图表展示了如何利用Plotly提升数据可视化的互动性。