2020年3月20-4月3日,DateWhale零基础入门数据挖掘,task2 数据分析 学习笔记。
题目:二手车交易价格的预测(https://tianchi.aliyun.com/competition/entrance/231784/information)
学习了3月23日直播的讲解,结合题目对于EDA数据探索性分析,进行了总结。从baseline角度,EDA数据分析可大致分为7个步骤。
一、函数载入
包含数据科学库、可视化库等。
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt #画图
import seaborn as sns
import missingno as msno
import pandas_profiling #生成数据报告的库
二、载入数据
1、载入训练集合测试集。该题目的总数据量超过40w,包含31列变量信息,其中15列为匿名变量。训练集有15万条,测试集A和测试集B分别有5万条。其中可以看到各列的性质特征如下:
- SaleID - 销售样本ID
- name - 汽车编码
- regDate - 汽车注册时间
- model - 车型编码
- brand - 品牌
- bodyType - 车身类型
- fuelType - 燃油类型
- gearbox - 变速箱
- power - 汽车功率
- kilometer - 汽车行驶公里
- notRepairedDamage - 汽车有尚未修复的损坏
- regionCode - 看车地区编码
- seller - 销售方
- offerType - 报价类型
- creatDate - 广告发布时间
- price - 汽车价格
- v_0', 'v_1', 'v_2', 'v_3', 'v_4', 'v_5', 'v_6', 'v_7', 'v_8', 'v_9', 'v_10', 'v_11', 'v_12', 'v_13','v_14' 【匿名特征,包含v0-14在内15个匿名特征】
2、通过程序简略观察数据
#1) 载入训练集和测试集;
path = './'
Train_data = pd.read_csv(path+'used_car_train_20200313/used_car_train_20200313.csv', sep=' ')
Test_data = pd.read_csv(path+'used_car_testA_20200313/used_car_testA_20200313.csv', sep=' ')
#2) 简略观察数据(head()+shape)
Train_data.head().append(Train_data.tail())
print(Train_data.shape)
会得到一个10*31的矩阵。
三、数据总览
1、相关统计量,通过调用describe,可以查看每列的统计量——个数count、平均值mean、方差std、最小值min、中位数25% 50% 75% 、最大值(8个参数)。通过查看这些信息主要为了能快速掌握数据的大概的范围,以及对异常值的判断。比如超出均值很大的数,三种中位数之间有较大差异或者非常近似,会影响其特征是否被重点考虑的范围(这一点的原理和机制还需要继续深入理解)
2、info用来了解数据每列的type,有助于了解是否存在除了NAN以外的特殊符号异常。
#1) 通过describe()来熟悉数据的相关统计量
Train_data.describe()
Test_data.describe()
#2) 通过info()来熟悉数据类型
Train_data.info()
Test_data.info()
四、数据检测
1、缺省值检测,查看每列(特征)存在的NAN情况,可将缺省值补充NAN。
#1) 查看每列的存在nan情况
Train_data.isnull().sum()
Test_data.isnull().sum()
# NAN可视化
missing = Train_data.isnull().sum()
missing = missing[missing > 0]
missing.sort_values(inplace=True)
missing.plot.bar()
# 可视化看下缺省值
msno.matrix(Train_data.sample(250))
msno.bar(Train_data.sample(1000))
# 可视化看下缺省值
msno.matrix(Test_data.sample(250))
msno.bar(Test_data.sample(1000)) #柱状图显示
#2) 查看异常值检测
Train_data.info()
Train_data['notRepairedDamage'].value_counts()
#发现除了notRepairedDamage 为object类型其他都为数字,课程材料中把几个不同的值都进行显示。
#发现-也为缺省值,把-替换成nan。
Train_data['notRepairedDamage'].replace('-', np.nan, inplace=True)
Train_data['notRepairedDamage'].value_counts()
Train_data.isnull().sum()
Test_data['notRepairedDamage'].value_counts()
2、异常值检测。如果类别特征中不同样本的差异严重,一般不会对预测有什么帮助,可以先删除,也可以保留继续数据挖掘,但一般意义不大。
Train_data["seller"].value_counts()
Train_data["offerType"].value_counts()
###
del Train_data["seller"]
del Train_data["offerType"]
del Test_data["seller"]
del Test_data["offerType"]
五、预测分布
Train_data['price']
Train_data['price'].value_counts()
#1) 总体分布概况
import scipy.stats as st
y = Train_data['price']
plt.figure(1); plt.title('Johnson SU')
sns.distplot(y, kde=False, fit=st.johnsonsu)
plt.figure(2); plt.title('Normal')
sns.distplot(y, kde=False, fit=st.norm)
plt.figure(3); plt.title('Log Normal')
sns.distplot(y, kde=False, fit=st.lognorm)
经分析,价格price不服从正态分布,所以在进行回归之前,要进行转换。天池官方给出的方案是无界约翰逊分布。
#2)查看skewness and kurtosis
sns.distplot(Train_data['price']);
print("Skewness: %f" % Train_data['price'].skew())
print("Kurtosis: %f" % Train_data['price'].kurt())
Train_data.skew(), Train_data.kurt()
sns.distplot(Train_data.skew(),color='blue',axlabel ='Skewness')
sns.distplot(Train_data.kurt(),color='orange',axlabel ='Kurtness')
#3) 查看预测值的具体频数
plt.hist(Train_data['price'], orientation = 'vertical',histtype = 'bar', color ='red')
plt.show()
查看频率,大于20000值的数目极少,这里也可把其当作特殊得值(异常值)直接填充或者删掉,再执行前面的转换操作。
# log变换 z之后的分布较均匀,可以进行log变换进行预测,这也是预测问题常用的trick
plt.hist(np.log(Train_data['price']), orientation = 'vertical',histtype = 'bar', color ='red')
plt.show()
六、特征分析
该题目共有31个特征。
1、数字特征。通过查看分析,方法有相关性分析,查看特征的偏度和峰值。
numeric_features.append('price')
print(numeric_features)
Train_data.head()
#1) 相关性分析
price_numeric = Train_data[numeric_features]
correlation = price_numeric.corr()
print(correlation['price'].sort_values(ascending = False),'\n')
f , ax = plt.subplots(figsize = (7, 7))
plt.title('Correlation of Numeric Features with Price',y=1,size=16)
sns.heatmap(correlation,square = True, vmax=0.8)
#2) 查看几个特征得 偏度和峰值
for col in numeric_features:
print('{:15}'.format(col),
'Skewness: {:05.2f}'.format(Train_data[col].skew()) ,
' ' ,
'Kurtosis: {:06.2f}'.format(Train_data[col].kurt())
)
第二步是进行可视化分析,主要包括3个方面:1)数字特征相互之间的关系可视化,2)多变量互相回归关系可视化,3)数字特征的分布可视化
#3) 每个数字特征得分布可视化
f = pd.melt(Train_data, value_vars=numeric_features)
g = sns.FacetGrid(f, col="variable", col_wrap=2, sharex=False, sharey=False)
g = g.map(sns.distplot, "value")
2、类别特征。主要包括查看分析、可视化。
查看分析设计unique分布。
## 1) unique分布
for fea in categorical_features:
print(Train_data[fea].nunique())
print(categorical_features)
可视化方面,常用的5类:箱型图可视化、小提琴图可视化(相当于进阶版的箱型图)、柱形图可视化、特征的每个类别频数可视化(count_plot),其他的还有直方图、密度曲线函数等。可视化分析便于我们查看数据的异常情况,以及不同数据间分布的对比。
#2) 类别特征箱形图可视化
# 因为 name和 regionCode的类别太稀疏了,这里我们把不稀疏的几类画一下
categorical_features = ['model',
'brand',
'bodyType',
'fuelType',
'gearbox',
'notRepairedDamage']
for c in categorical_features:
Train_data[c] = Train_data[c].astype('category')
if Train_data[c].isnull().any():
Train_data[c] = Train_data[c].cat.add_categories(['MISSING'])
Train_data[c] = Train_data[c].fillna('MISSING')
def boxplot(x, y, **kwargs):
sns.boxplot(x=x, y=y)
x=plt.xticks(rotation=90)
f = pd.melt(Train_data, id_vars=['price'], value_vars=categorical_features)
g = sns.FacetGrid(f, col="variable", col_wrap=2, sharex=False, sharey=False, size=5)
g = g.map(boxplot, "value", "price")
print(Train_data.columns)
#3) 类别特征的小提琴图可视化
catg_list = categorical_features
target = 'price'
for catg in catg_list :
sns.violinplot(x=catg, y=target, data=Train_data)
plt.show()
categorical_features = ['model',
'brand',
'bodyType',
'fuelType',
'gearbox',
'notRepairedDamage']
#4) 类别特征的柱形图可视化
def bar_plot(x, y, **kwargs):
sns.barplot(x=x, y=y)
x=plt.xticks(rotation=90)
f = pd.melt(Train_data, id_vars=['price'], value_vars=categorical_features)
g = sns.FacetGrid(f, col="variable", col_wrap=2, sharex=False, sharey=False, size=5)
g = g.map(bar_plot, "value", "price")
#5) 类别特征的每个类别频数可视化(count_plot)
def count_plot(x, **kwargs):
sns.countplot(x=x)
x=plt.xticks(rotation=90)
f = pd.melt(Train_data, value_vars=categorical_features)
g = sns.FacetGrid(f, col="variable", col_wrap=2, sharex=False, sharey=False, size=5)
g = g.map(count_plot, "value")
七、生成报告
调用pandas_profiling库,可以生产一个比较全面的可视化和数据报告,生成结果为html文件。
pfr = pandas_profiling.ProfileReport(Train_data)
pfr.to_file("./example.html")