前言
? ? ? ? 一年半前写了二手车数据获取的博客,期间经历了给导师做项目、找工作、实习、写论文,终于闲下来可以继续更新数据处理部分了。 ? ? ? ? 数据获取部分请看这里:Python数据分析-二手车数据用于机器学习二手车价格预测 ? ? ? ? 相关代码我放在我码云仓库中,感兴趣的同学可以clone、star,链接:码云仓库 ? ? ? ? 同时,分享我的秘密基地,懂得同学已经拿出手机了,顺便贴个链接:吉吉的机器学习乐园 ? ? ? ? 不想执行代码获取数据的同学,或着急使用的同学,我都把数据放在秘密基地了。
一、数据
? ? ? ? 原始数据维度为:93738*212 ? ? ? ? 获取时间为:2020年7月25日 ? ? ? ? 数据处理十分重要,一个机器学习模型预测结果的好坏与数据处理有直接关联。每个人处理数据的思维和方式都不一样,因此本文只是依据我的一些学习经验进行数据处理,给大家当个baseline~
二、处理过程
1.引入库
代码如下:
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
import sys
import seaborn as sns
import warnings
import datetime
warnings.filterwarnings("ignore")
plt.rcParams['font.sans-serif'] = ['SimHei']
plt.rcParams['axes.unicode_minus'] = False
pd.set_option('display.max_rows', 100,'display.max_columns', 100,"display.max_colwidth",1000,'display.width',1000)
2.读入数据
代码如下:
data = pd.read_excel("cars_info.xlsx", na_values=np.nan)
3.删除无效列与填充空值
? ? ? ? 数据的许多列包含大量的空值和单一数据,当这些数据超过一定量时,对模型来说是无效的,因此先将这一部分数据进行删除。
代码如下:
for c in data.columns:
if data[c].isna().sum() > 80000:
data.drop([c], axis=1, inplace=True)
for c in data.columns:
if data[c].isin(["无"]).sum() > 60000:
data.drop([c], axis=1, inplace=True)
data.drop(['长*宽*高(mm)'], axis=1, inplace=True)
for c in data.columns:
if data[c].isin(["标配"]).sum() > 60000:
print(c, data[c].isin(["标配"]).sum())
data.drop([c], axis=1, inplace=True)
data.dropna(axis=0,subset = ["售价", "排量(L)"], inplace=True)
data.drop(['厂商新车指导价'], axis=1, inplace=True)
data['过户记录'].fillna(0, inplace=True)
data['载客/人'].fillna(int(data['载客/人'].mean()), inplace=True)
4.数值型数据处理
? ? ? ? 通过Excel表我们可以发现,有些列可以完全处理成数值型数据。剔除这些列中的异常数据,并且为空值进行填充,可以使用平均值或众数进行填充。
代码如下:
numerical_col = ['售价', '新车售价', '行驶里程', '过户记录',
'载客/人', '排量(L)', '最高车速(km/h)', '官方0-100km/h加速(s)',
'工信部综合油耗(L/100km)', '长度(mm)', '宽度(mm)', '高度(mm)',
'轴距(mm)', '前轮距(mm)', '后轮距(mm)', '车门数', '油箱容积(L)',
'整备质量(kg)', '最小离地间隙(mm)', '排量(mL)', '气缸数(个)',
'每缸气门数(个)', '压缩比', '最大马力(Ps)', '最大功率(kW)',
'最大扭矩(N·m)'
]
numerical_df = data[numerical_col]
for c in numerical_col[5:]:
numerical_df[c] = numerical_df[c].replace("无", np.nan).replace("false", np.nan).replace("未知", np.nan)
mean_fill_col = ['排量(L)', '最高车速(km/h)', '官方0-100km/h加速(s)',
'工信部综合油耗(L/100km)', '长度(mm)', '宽度(mm)', '高度(mm)',
'轴距(mm)', '前轮距(mm)', '后轮距(mm)', '油箱容积(L)',
'整备质量(kg)', '最小离地间隙(mm)', '排量(mL)', '压缩比',
'最大马力(Ps)', '最大功率(kW)', '最大扭矩(N·m)'
]
many_fill_col = ['车门数', '气缸数(个)', '每缸气门数(个)']
numerical_df = numerical_df.astype(float)
for c in mean_fill_col:
numerical_df[c].fillna(numerical_df[c].mean(), inplace=True)
for c in many_fill_col:
numerical_df[c].fillna(4, inplace=True)
data[ numerical_col ] = numerical_df
def pickNum(df, c):
if '-' in df[c]:
num_list = df[c].split('-')
return num_list[0]
elif '―' in df[c]:
num_list = df[c].split('―')
return num_list[0]
elif '~' in df[c]:
num_list = df[c].split('~')
return num_list[0]
elif '/' in df[c]:
num_list = df[c].split('/')
return num_list[0]
else:
return df[c]
pickNum_col = ['座位数', '行李厢容积(L)', '最大功率转速(rpm)', '最大扭矩转速(rpm)']
data[pickNum_col] = data[pickNum_col].astype(str)
for c in pickNum_col:
data[c] = data.apply(lambda x:pickNum(x, c), axis=1)
for c in pickNum_col:
data[c] = data[c].replace("无", np.nan).replace("false", np.nan).replace("未知", np.nan)
data[pickNum_col] = data[pickNum_col].astype(float)
data['座位数'].fillna(5, inplace=True)
for c in pickNum_col[1:]:
data[c].fillna(data[c].mean(), inplace=True)
5.日期型数据处理
? ? ? ? 数据中包含许多日期数据,我将它们转换成天数差,即用数据获取的时间减去对应的时间。
代码如下:
date_col = ['商业险过期日期','交强险过期日期', '注册日期', '出厂日期', '车船税过期日期']
data['数据获取日期'] = '2020-07-25'
date_col.append('数据获取日期')
def calDate(df, c):
if pd.isnull(df['出厂日期']):
return np.nan
else:
d1=datetime.datetime.strptime('2020-07-25',"%Y-%m-%d")
d2=datetime.datetime.strptime(df[c],"%Y-%m-%d")
diff_days=d1-d2
return diff_days.days
for c in date_col[:-1]:
data[c] = data[c].replace("--", np.nan)
for c in date_col[:-1]:
data[c+'差(天)'] = data.apply(lambda x:calDate(x, c), axis=1)
new_date_col = ['商业险过期日期差(天)','交强险过期日期差(天)', '注册日期差(天)', '出厂日期差(天)', '车船税过期日期差(天)']
for c in new_date_col:
data[c].fillna(data[c].mean(), inplace=True)
data.drop(date_col, axis=1, inplace=True
6.二值型数据处理
? ? ? ? 许多列的数据要么为"有",要么为"无"。类似这种的数据我们称为"二值型"数据,可以将其转化为0-1的形式。
代码如下:
zero_one_col_names = ['前排侧气囊', '无钥匙启动系统', 'TRC牵引力控制系统', '上坡辅助', '电动天窗',
'真皮方向盘', '日间行车灯', '自动头灯', '后视镜加热', '后雨刷', '后座出风口',
'4S店保养', '原始购车/过户发票', '车辆购置税完税证明']
for c in zero_one_col_names:
data[c] = data[c].replace("无", 0).replace("false", 0).replace("true", 1).replace("标配", 1).replace("false", 0).replace("否", 0).replace("是", 1).replace("有(已见发票)", 1).replace("有(未见发票)", 0).replace("已缴税(未见证明)", 0).replace("已缴税(已见证明)", 1).replace("K请问欺负我测了没人粉粉嫩嫩妇女。。佛方法v。。", 0)
data[c].fillna(0, inplace=True)
7.One-Hot型数据处理
? ? ? ? 当一列值可以被分成多个类别时,我们可以将数据处理成独热编码(One-Hot)的形式,建议类别的个数超过10的时候就不要使用独热编码了,因为会导致数据过于稀疏,它的详细作用就不介绍了,朋友们自行百度。
代码如下:
one_hot_col_names = ['进气形式', '气缸排列形式', '配气机构', '燃油标号', '供油方式', '缸盖材料',
'缸体材料', '燃油形式', '变速箱类型', '驱动方式', '助力类型', '车体结构',
'前制动', '后制动', '驻车制动类型', '备胎规格', '定速巡航', '真皮座椅',
'变速器类型', '燃料类型', '车身颜色', '挡位个数']
data['挡位个数'] = data['挡位个数'].replace("无", "无级变速")
data['车身颜色'] = data['车身颜色'].replace("--", np.nan)
data['真皮座椅'] = data['真皮座椅'].replace(",", np.nan)
data['定速巡航'] = data['定速巡航'].replace("/", np.nan).replace("田......看", np.nan)
data['助力类型'] = data['助力类型'].replace("无助力", "无")
for c in one_hot_col_names:
data[c] = data[c].replace("false", "无")
data[c].fillna("无", inplace=True)
one_hot_data = pd.get_dummies(data[one_hot_col_names])
data = pd.concat([data,one_hot_data],axis = 1)
data.drop(one_hot_col_names, axis=1, inplace=True)
final_col = list(data.describe().columns)
final_data = data[final_col]
final_data.to_excel("final_data.xlsx", index=False)
结语
? ? ? ? 经过以上步骤的数据处理,我们将原始数据转换成可以放入机器学习模型的数据了。这里的数据处理过程比较简单,其中的一些操作也可以简单的理解成特征工程的过程(毕竟只是baseline),有能力的同学也可以按照自己的想法进行数据处理和特征工程。 ? ? ? ? 最后的数据维度为:93738*190 ? ? ? ? 下一期将进行机器学习的模型训练,以及实验结果的分析。
|