肿瘤康复网,内容丰富有趣,生活中的好帮手!
肿瘤康复网 > #数据挖掘--第1章:EDA数据探索性分析

#数据挖掘--第1章:EDA数据探索性分析

时间:2020-09-02 07:29:02

相关推荐

#数据挖掘--第1章:EDA数据探索性分析

一、序言二、EDA的意义三、EDA的流程

一、序言

本系列博客面向初学者,只讲浅显易懂易操作的知识。包含:数据分析、特征工程、模型训练等通用流程。将会一步一步引领大家完成一次完整的机器学习案例。点击下载 本系列博客所用数据集,提取码: r6m6。本系列使用工具:Pycharm+Python3.7.6

本系列博客主要面向初学者,以知识性扩充为主,如有笔误,请联系反馈

本系列博客代码并非都是必需,某些代码其实对于本问题而言并不合理,但是为了教学而补充

数据相关字段解释:

二、EDA的意义

EDA是指对已有的数据(特别是调查或观察得来的原始数据)在尽量少的先验假定下进行探索,通过作图、制表、方程拟合、计算特征量等手段探索数据的结构和规律的一种数据分析方法。

在拿到数据后,首先要进行的是数据探索性分析(Exploratory Data Analysis),它可以有效的帮助我们熟悉数据集、了解数据集。初步分析变量间的相互关系以及变量与预测值之间的关系,并且对数据进行初步处理,如:数据的异常和缺失处理等,以便使数据集的结构和特征让接下来的预测问题更加可靠。通常的步骤如下:

1.对于数据的初步分析(直接查看数据,或.sum(), .mean(),.descirbe()等统计函数)可以从:样本数量,训练集数量,是否有时间特征,是否是时许问题,特征所表示的含义(非匿名特征),特征类型(string,int,float,time),特征的缺失情况(注意缺失的在数据中的表现形式,有些是空的有些是”NAN”符号等),特征的均值方差情况。

2.分析记录某些特征值缺失占比30%以上样本的缺失处理,有助于后续的模型验证和调节,分析特征应该是填充(填充方式是什么,均值填充,0填充,众数填充等),还是舍去,还是先做样本分类用不同的特征模型去预测。

3.对于异常值做专门的分析,分析特征异常的Label是否为异常值(或者偏离均值较远或者是特殊符号),异常值是否应该剔除,还是用正常值填充,是记录异常,还是机器本身异常等。

4.对于Label做专门的分析,分析标签的分布情况等。

5.进一步分析;可以通过对特征作图,特征和Label联合做图(统计图,离散图),直观了解特征的分布情况,通过这一步也可以发现数据之中的一些异常值等,通过箱型图分析一些特征值的偏离情况,通过特征和特征联合作图、特征和Label联合作图,分析其中的一些关联性。

异常值检测:

异常值的检测通常是需要结合数据分布一起考量的,这里只是简单说下理论。

常见方法有:

a.均方差、正态分布的 ±3σ 标准差,大约99.7%会在三个标准差范围内。

b.箱形图和散点图,通过可视化的方法来直观的看出离群点。

c.算法方法,聚类,孤立森林等。

注意点:

1.以上说的都只适用于连续型特征。

2.离散型特征更趋向于人的主观判断,比如某些类别过少等。

3.离散型特征,主要处理目标变量的不平衡问题。

4.异常值并不存在完美严格的标准可以适用于一切情况,最重要的还是具体问题具体分析。

三、EDA的流程

1、载入数据并简略观察数据

import numpy as npimport pandas as pdimport seaborn as snsimport missingno as msnoimport scipy.stats as stimport matplotlib.pyplot as plt # 1.1train_data = pd.read_csv("二手车交易价格预测/used_car_train_.csv", ' ')# 因为 SaleID 是明显无用特征,直接筛去del train_data['SaleID']

在Pycharm的科学计算模式下,直接点击查看train_data。

2、总览数据概况

- 在 describe 中有每一列的统计量、均值、标准差、最小值、中位数25% 50% 75%以及最大值。可以帮助我们快速掌握数据的大概范围和数据的异常判断。

- 通过 info 来了解每列的 type 有助于了解是否存在除 Nan 以外的符号异常

- 通过 isnull().sum() 查看每列缺失情况,nan 可以使用如众数、均值等进行填充,但若某一列存在过多 nan 就可以考虑将此列删除。

# 2.1# 通过 info 查看数据类型print(train_data.info())

# 2.2# 在这里我们可以看到除 notRepairedDamage 外其它字段的类型均为数字类型# 因此我们可以查看一下 notRepairedDamage 的值的分布情况print(train_data['notRepairedDamage'].value_counts())

# 2.3# 在这里我们看到有一个值为 “-” ,而其它值为数字,说明这个值是无意义的,也就是 Nan# 因此我们在这里将其替换为 -1train_data['notRepairedDamage'].replace("-", -1., inplace=True)# 因为这个数据代表车辆是否有过修里破损,因此为了后续方便,将其数据类型转化为 int32train_data['notRepairedDamage'] = train_data['notRepairedDamage'].astype(np.float32).astype(np.int32)# 再次查看,已经都是数字了print(train_data.info())

# 2.4# 通过 describe 和 matplotlib 可视化查看数据的相关统计量train_data_describe = train_data.describe()columns = train_data_describe.columnsindex = train_data_describe.index[1:]colors = ['blue', 'red', 'green', 'black', 'pink', 'purple', 'gray', 'yellow']plt.figure(figsize=(15, 10))for i in range(len(columns) - 16):ax = plt.subplot(4, 4, i + 1)ax.set_title(columns[i])for j in range(len(index)):plt.bar(index[j], train_data_describe.loc[index[j], columns[i]], color=colors[j])plt.show()del columns, index, colors, i, j, ax# 可以从中看到 seller 、 offerType 和 power 的数据不太正常# 进一步查看分析 train_data_describe 得知:# power、seller 的 mean 过于接近 min,offerType 的 mean=min=max

# 2.5# 查看上述异常列的值的分布情况for column in ['seller', 'offerType', 'power']:print(column + '\n', train_data[column].value_counts(), '\n')del column# 分析得知,power 仅仅只是 max 太大了# 而 seller 和 offerType 特征严重倾斜,对预测没有什么帮助,故可选择删除del train_data['seller'], train_data['offerType']

# 2.6# 查看一下 nan 的分布情况train_data['notRepairedDamage'].replace(-1, np.nan, inplace=True)print(train_data.isnull().sum())train_data['notRepairedDamage'].replace(np.nan, -1, inplace=True)# 可视化查看 nan 的分布情况msno.matrix(train_data)plt.show()# 如果某个特征的 nan 过多,则可选择性将其删除# 这里我们看到虽然 notRepairedDamage 这个特征的 nan 高达 24324# 但是直观上考虑到这个变量对于二手车价格的影响应该很大,所以这里就不删除了

3、了解预测值的分布

# 3.1# 尝试多种方法,拟合价格分布# 可参考 /developer/ask/112712 选取合适的拟合方法y_train = train_data['price']fits = [st.johnsonsu, st.exponweib]plt.figure(figsize=(6, 3 * len(fits)))for i in range(len(fits)):ax = plt.subplot(len(fits), 1, i+1)ax.set_title(str(fits[i]))sns.distplot(y_train, kde=False, fit=fits[i])plt.show()del fits, ax, i# 由图可知无界约翰逊分布和 exponweib 分布拟合效果很好

# 3.2# 查看价格的偏度(skewness)和峰度(kurtosis)# 有关偏度和峰度的介绍见链接 /qq_36523839/article/details/88671873print("skewness is ", y_train.skew())print("kurtosis is ", y_train.kurt())

# 3.3# 从上面的拟合效果中可以看出价格大致服从 exp^-1 的指数分布# 但是由于指数分布越往后分布越稀疏,因此尝试对数据尝试进行 log 变换。# log 变换后再次绘制频数分布图,发现,明显缩小了价格的分布区间,# 进行某种函数变换后再进行预测,这也是预测问题常用的tricky_train = np.log(y_train)plt.hist(y_train)plt.show()

# 4.1# 查看每个特征的 unique 数量columns = train_data.columnsfor i in columns:print(i, len(train_data[i].unique()))del i, columns

# 4.2# 根据特征含义,人工筛选连续型特征和离散特征numeric_features = ['creatDate', 'regDate', 'power', 'kilometer', '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']categorical_features = ['name', 'model', 'brand', 'bodyType', 'fuelType', 'gearbox', 'notRepairedDamage','regionCode']

# 4.3# 对连续性特征和离散型特征分别进行相关性分析,并且绘制相关性矩阵numeric_feature_corr = train_data[['price'] + numeric_features].corr()categorical_feature_corr = train_data[['price'] + categorical_features].corr()plt.figure(figsize=(7, 7))plt.title("Correlation of numeric feature")sns.heatmap(numeric_feature_corr, square=True)plt.show()print("Correlation of numeric feature with price:\n", numeric_feature_corr['price'], '\n')plt.figure(figsize=(7, 7))plt.title("Correlation of categorical feature")sns.heatmap(categorical_feature_corr, square=True)plt.show()print("Correlation of numeric feature with price:\n", categorical_feature_corr['price'], '\n')del categorical_feature_corr, numeric_feature_corr

# 4.6# 让连续型特征的频率分布可视化f = pd.melt(train_data, value_vars=numeric_features)sns.FacetGrid(f, col="variable", col_wrap=4, sharex=False, sharey=False).map(sns.distplot, "value")plt.show()del f

# 4.7# 观察分布非常不均匀的数据,进一步绘制其与 price 之间的散点图,观察相关关系columns = ['power', 'v_1', 'v_2', 'v_5', 'v_6', 'v_7', 'v_11', 'price']sns.set()sns.PairGrid(train_data[columns], x_vars=columns[:len(columns) - 1], y_vars=['price']).map(sns.scatterplot)plt.show()del columns

# 4.8# 绘制离散特征箱型图# 关于箱型图和小提琴图请参考:/zhhfan/p/11344310.html# 让 X 轴上的标签为垂直方向def boxplot(x, y, **kwargs):sns.boxplot(x=x, y=y)plt.xticks(rotation='vertical', **kwargs)# 由 4.1 得知,name 的 unique 为 99662,regionCode 的 unique 为 7905,类别过于稀疏,因此这里不予考虑categorical_features = ['model', 'brand', 'bodyType', 'fuelType', 'gearbox', 'notRepairedDamage']# 将数据类型转换为 category,并且填充 Nan 为 Missingtrain_data['notRepairedDamage'].replace(-1, np.nan, inplace=True)for i in categorical_features:train_data[i] = train_data[i].astype('category')if train_data[i].isnull().any():train_data[i].cat.add_categories(['missing'], inplace=True)train_data[i].fillna('missing')# 数据融合并绘制箱型图,由于 model 和 brand 类别有点多,所以单独绘制它俩f = pd.melt(train_data, id_vars='price', value_vars=categorical_features[2:])plt.figure(figsize=(10, 10))sns.FacetGrid(f, col='variable', col_wrap=2, sharex=False, sharey=False).map(boxplot, 'value', 'price')plt.show()# 单独绘制 model 的箱型图plt.figure(figsize=(60, 4.8))plt.xticks(rotation='vertical')sns.boxplot(x=train_data[categorical_features[0]], y=train_data['price'])plt.show()# 单独绘制 brand 的箱型图plt.figure(figsize=(9, 4.8))sns.boxplot(x=train_data[categorical_features[1]], y=train_data['price'])plt.show()del i

# 4.9# 绘制离散特征的小提琴图# 数据融合并小提琴图,由于 model 和 brand 类别有点多,所以单独绘制它俩sns.FacetGrid(f, col='variable', col_wrap=2, sharex=False, sharey=False).map(sns.violinplot, 'value', 'price')# noinspection DuplicatedCodeplt.show()# 单独绘制 model 的小提琴图plt.figure(figsize=(60, 4.8))plt.xticks(rotation='vertical')sns.violinplot(x=train_data[categorical_features[0]], y=train_data['price'])plt.show()# 单独绘制 brand 的小提琴图plt.figure(figsize=(9, 4.8))sns.violinplot(x=train_data[categorical_features[1]], y=train_data['price'])plt.show()del f

# 4.10# 绘制柱形图f = pd.melt(train_data, id_vars=['price'], value_vars=categorical_features)sns.FacetGrid(f, col="variable", col_wrap=2, sharex=False, sharey=False).map(sns.barplot, "value", "price")plt.show()

# 4.11# 绘制频数图f = pd.melt(train_data, value_vars=categorical_features)sns.FacetGrid(f, col="variable", col_wrap=2, sharex=False, sharey=False, size=5).map(sns.countplot, "value")plt.show()

如果觉得《#数据挖掘--第1章:EDA数据探索性分析》对你有帮助,请点赞、收藏,并留下你的观点哦!

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。