新闻中心

探索式数据分析

2023-03-20
浏览次数:
返回列表

背景

在开始调用机器学习、深度学习库进行训练模型之前,首先要对数据进行探索性数据分析。这能让你了解数据,对手中数据的特征、噪音、缺失等有一个初步的认识。这样你能在接下来的数据预处理中清晰的明白自己需要选择哪个特征、如何清洗数据等。

另外,理解本文内容需要你了解python,统计数据分析等基础知识。

本文适合数据挖掘、机器学习刚入门的同学,对于已经入门的同学也有一定的参考价值。如果您觉得文章有不足之处,请多多批评指正。

关键字

数据分析、单变量数据分析、多元数据分析、python、统计数据分析

数据案例来自于:根据房屋历史销售数据,对房价(“SalePrice”)进行预测

https://www.kaggle.com/c/house-prices-advanced-regression-techniques

我将给大家展示的操作类似于:

了解问题。研究每个变量,并对它们对这个问题的意义和重要性进行分析。单变量研究。关注因变量(SalePrice),并尝试进一步了解它。多变量研究。了解因变量和自变量之间的关系。基本清洁。清理数据集并处理缺失的数据,离群值和分类变量。测试假设。检查数据是否符合大多数多元数据分析技术所要求的假设。

现在开始!

import pandas as pd import matplotlib.pyplot as plt import seaborn as sns import numpy as np from scipy.stats import norm from sklearn.preprocessing import StandardScaler from scipy import stats import warnings warnings.filterwarnings(ignore) %matplotlib inline #导入数据 df_train = pd.read_csv(../input/train.csv) #查看数据列名称 df_train.columnsIndex([Id, MSSubClass, MSZoning, LotFrontage, LotArea, Street, Alley, LotShape, LandContour, Utilities, LotConfig, LandSlope, Neighborhood, Condition1, Condition2, BldgType, HouseStyle, OverallQual, OverallCond, YearBuilt, YearRemodAdd, RoofStyle, RoofMatl, Exterior1st, Exterior2nd, MasVnrType, MasVnrArea, ExterQual, ExterCond, Foundation, BsmtQual, BsmtCond, BsmtExposure, BsmtFinType1, BsmtFinSF1, BsmtFinType2, BsmtFinSF2, BsmtUnfSF, TotalBsmtSF, Heating, HeatingQC, CentralAir, Electrical, 1stFlrSF, 2ndFlrSF, LowQualFinSF, GrLivArea, BsmtFullBath, BsmtHalfBath, FullBath, HalfBath, BedroomAbvGr, KitchenAbvGr, KitchenQual, TotRmsAbvGrd, Functional, Fireplaces, FireplaceQu, GarageType, GarageYrBlt, GarageFinish, GarageCars, GarageArea, GarageQual, GarageCond, PavedDrive, WoodDeckSF, OpenPorchSF, EnclosedPorch, 3SsnPorch, ScreenPorch, PoolArea, PoolQC, Fence, MiscFeature, MiscVal, MoSold, YrSold, SaleType, SaleCondition, SalePrice], dtype=object)

OK 那么我们能做什么...?

为了理解我们的数据,我们可以查看每个变量并尝试了解它们的业务含义以及与该问题的业务相关性。我知道这很耗时,但是在了解数据的初期理解业务逻辑是非常必要的。

我们可以创建一个包含以下各列的Excel电子表格:

变量-变量名。类型-标识变量的类型。此字段有两个可能的值:“数值”或“类别”。 “数值”是指值是数值型(尤其是连续的)的变量,“类别”是指值是类别(尤其是离散的)的变量。分类-标识变量的分类。我们可以根据数据的业务逻辑定义三个可能的分类:build,space和location。当我们说“build”时,是指与建筑物的物理特性相关的变量(例如“ OverallQual”)。当我们说“space”时,是指一个报告房屋空间属性的变量(例如“ TotalBsmtSF”)。最后,当我们说“location”变量时,是指提供有关房屋所在位置的信息(例如“neighber”)。期望-对“ SalePrice”影响程度的猜测。我们可以根据业务逻辑,使用带有“高”,“中”和“低”的分类标尺作为可能的猜测值。后面还会有对于猜测的验证。验证-快速浏览数据后,我们验证的关于“SalePrice”变量影响程度的结论并填写“高”,“中”和“低”的分类标尺作为验证后的结论。总结-对数据的总体性评论。

尽管“类型”和“分类”仅供将来参考,但“期望”一栏很重要,因为它将帮助我们产生对于数据整体认知。为了更加准确地、高效的在后期训练我们的模型,我们应该阅读所有变量的描述,并一步步地问自己(或者和业务方反复的讨论、请教业务知识):

我们在购买房屋时会考虑这个变量因素吗? (例如,当我们想到自己梦魅以求的房子时,我们是否在乎它的“墙体贴面类型”?)。这一步有助于选择对于预测房价相关性强的特征。如果是这样,此变量将有多重要? (例如,在外部使用“优质”材料而不是“差”的影响?而使用“优质”材料而不是“良好”的影响是什么?)。这一步有助于选择对于预测房价相关性强的特征。此信息是否已在其他任何变量中描述过? (例如,如果“ LandContour”给出了属性的平坦度,我们是否真的需要知道“ LandSlope”?)。这一步有助于甄别并过滤那些有共线性的特征,以提高训练模型的效率。

经过以上步骤后,我们可以过滤Excel并仔细查看带有“高”期望的变量。然后,我们可以观察这些变量与“ SalePrice”之间的一些散点图,在“验证”列中填写结果,这只是对我们期望值的修正。

我们完成这个过程并得出结论,以下变量可以在此问题中发挥重要作用:

TotalQualYearBuiltTotalBsmtSFGrLivArea

接下来,我们要通过数据可视化和数据分析的方式,客观的评价我们的讨论结果。

分析预测目标:“ SalePrice”

初步观察“SalePrice”数据的统计描述

df_train[SalePrice].describe()count 1460.000000 mean 180921.195890 std 79442.502883 min 34900.000000 25% 129975.000000 50% 163000.000000 75% 214000.000000 max 755000.000000 Name: SalePrice, dtype: float64

使用seaborn库可以更加直观的看到数据分布:

#histogram sns.distplot(df_train[SalePrice]);

根据上面的图,我们能得出结论:

偏离正态分布有明显的正偏度表现出顶峰

计算偏度和峰度。关于偏度和峰度请参考:https://baike.baidu.com/item/%E5%81%8F%E5%BA%A6/8626571?fr=aladdin

#skewness and kurtosis print("Skewness: %f" % df_train[SalePrice].skew()) print("Kurtosis: %f" % df_train[SalePrice].kurt()) Skewness: 1.882876 Kurtosis: 6.536282

研究与“ SalePrice”相关的变量

接下来,我们要研究哪些变量(上文中讨论过的)与SalePrice有相关性。这将有助于筛选哪些高度相关的特征,剔除没用的特征进而提高训练模型的效率。

“SalePrice”与数值型变量的关系

#scatter plot grlivarea/saleprice var = GrLivArea data = pd.concat([df_train[SalePrice], df_train[var]], axis=1) data.plot.scatter(x=var, y=SalePrice, ylim=(0,800000));

从上图观察, 似乎“ SalePrice”和“ GrLivArea”有线性关系。

#scatter plot totalbsmtsf/saleprice var = TotalBsmtSF data = pd.concat([df_train[SalePrice], df_train[var]], axis=1) data.plot.scatter(x=var, y=SalePrice, ylim=(0,800000));

“ TotalBsmtSF”和“ SalePrice”似乎也有线性(指数?)相关性。一切都发生了变化。 此外,很明显,有的数据(可能是离群值)也没有这种相关性。

与分类特征的关系

#box plot overallqual/saleprice var = OverallQual data = pd.concat([df_train[SalePrice], df_train[var]], axis=1) f, ax = plt.subplots(figsize=(8, 6)) fig = sns.boxplot(x=var, y="SalePrice", data=data) fig.axis(ymin=0, ymax=800000);var = YearBuilt data = pd.concat([df_train[SalePrice], df_train[var]], axis=1) f, ax = plt.subplots(figsize=(16, 8)) fig = sns.boxplot(x=var, y="SalePrice", data=data) fig.axis(ymin=0, ymax=800000); plt.xticks(rotation=90);

“ SalePrice”与“ OverallQual”,也似乎有一定相关性。

YearBuilt与SalePrice就没有很强的趋势,但我想说“ SalePrice”比起在旧房子上更倾向于在新房子上花费更多的钱。

注意:我们不知道“ SalePrice”是否为固定价格。 不变价格试图消除通货膨胀的影响。 如果“ SalePrice”不是固定价格,则应该是固定价格,因此多年来的价格是可比的。

综上所述

我们可以得出以下结论:

“ GrLivArea”和“ TotalBsmtSF”似乎与“ SalePrice”线性相关。 两种关系都是正的,这意味着随着一个变量增加,另一个也增加。 在“ TotalBsmtSF”的情况下,我们可以看到线性关系的斜率特别高。“ OverallQual”和“ YearBuilt”似乎也与“ SalePrice”相关。 在“ OverallQual”的情况下,这种关系似乎更加牢固,其中的方框图显示了销售价格如何随着整体质量而增加。

我们只是分析了四个变量,但是还有许多其他的我们需要分析。 这里的技巧似乎是正确特征的选择(特征选择),而不是它们之间复杂关系的定义(特征工程)。

就是说,在数据挖掘的过程中,让我们将金子与沙子分开!

等等,我们在上文中使用了很多“似乎”,这是什么意思?!我们能不能确定这些变量之间的关系呢?让我们来看下文。

使用相关性确定特征之间的“纽带”

到目前为止,我们只是按照直觉(上文中,所谓的“似乎”)来分析我们认为重要的变量。 尽管我们努力使分析具有客观性,但我们必须说,我们的出发点是主观的。作为工程师,我对这种方法不满意! 我所有的教育都是关于培养专业的,能够克服主观的、先入为主的“老百姓式的思维”。

因此,让我们克服惯性并进行更客观的分析。

相关矩阵(热图样式)

“ SalePrice”相关矩阵(缩放的热图样式)。

关联最密切的变量之间的散点图

#相关矩阵 corrmat = df_train.corr() f, ax = plt.subplots(figsize=(12, 9)) sns.heatmap(corrmat, vmax=.8, square=True);

我认为,此热图是快速了解我们的各个特征相互关系的最佳方法。

乍一看,有两个红色正方形引起了我的注意。第一个引用“ TotalBsmtSF”和“ 1stFlrSF”变量,第二个引用“ GarageX”变量。两种情况都表明这些变量之间的相关性有多重要。实际上,这种相关性是如此之强,以至于可以指示多重共线性的情况。如果我们考虑这些变量,我们可以得出结论,它们给出的信息几乎相同,因此确实存在多重共线性。热图非常适合检测这种情况,在像特征一样由特征选择主导的问题中,热图是必不可少的工具。

引起我注意的是与“ SalePrice”相关性高的那些特征。我们可以看到除了我们猜到的“ GrLivArea”,“ TotalBsmtSF”和“ OverallQual”,还可以看到许多其他变量,应予以考虑。这就是我们接下来要做的。

与SalePrice相关top10高的相关矩阵

#saleprice correlation matrix k = 10 #number of variables for heatmap cols = corrmat.nlargest(k, SalePrice)[SalePrice].index cm = np.corrcoef(df_train[cols].values.T) sns.set(font_scale=1.25) hm = sns.heatmap(cm, cbar=True, annot=True, square=True, fmt=.2f, annot_kws={size: 10}, yticklabels=cols.values, xticklabels=cols.values) plt.show()

根据上图,这些是与“ SalePrice”最相关的变量。我对此的结论:

“ OverallQual”,“ GrLivArea”和“ TotalBsmtSF”与“ SalePrice”相关较高。确认了我们在前面的讨论。“ GarageCars”和“ GarageArea”也是一些最相关的变量。但是,正如我们在最后一个小节中讨论的,适合车库的汽车数量是车库面积的结果。 “ GarageCars”和“ GarageArea”就像“孪生兄弟”,具有高共线性。我们将无法区分它们。因此,我们在分析中只需要这些变量之一(由于与“ SalePrice”的相关性较高,因此可以保留“ GarageCars”)。“ TotalBsmtSF”和“ 1stFloor”也是孪生兄弟。我们可以保留TotalBsmtSF只是说我们的第一个猜测是正确的。“ TotRmsAbvGrd”和“ GrLivArea”,又是孪生兄弟。似乎“ YearBuilt”与“ SalePrice”略相关。我开始觉得我们应该做一些时间序列分析以实现这一点。我将把它作为后续讲解。

让我们继续对上面具有高相关性(top10)的特征画出散点图。

#scatterplot sns.set() cols = [SalePrice, OverallQual, GrLivArea, GarageCars, TotalBsmtSF, FullBath, YearBuilt] sns.pairplot(df_train[cols], size = 2.5) plt.show();

尽管我们已经了解了一些主要数据,但此巨型散点图为我们提供了有关变量关系的合理思路。

我们可能会发现有趣的数字之一是“ TotalBsmtSF”和“ GrLiveArea”之间的数字。在此图中,我们可以看到点画了一条直线,几乎就像一个边界。完全有道理的是,大多数点都位于该线以下。地下室的面积可以等于地面上的居住面积,但是地下室的面积不能大于地面上的居住面积(除非您要购买防空洞或者菜窖!)。

关于“ SalePrice”和“ YearBuilt”的图也可以使我们思考。在“点云”的底部,我们看到的几乎是一个隐秘的指数函数。我们也可以在“点云”的上限中看到相同的趋势。另外,请注意有关过去几年的点集如何趋于保持在此限制之上(我只是想说现在价格上涨得更快)。

好的,到目前为止,足够进行测试。让我们前进到缺失的地方:缺失的数据!

缺少数据

考虑丢失数据时的重要问题:

丢失的数据有多普遍?丢失数据是随机的还是有规律的?

出于实际原因,这些问题的答案很重要,因为缺少数据可能意味着样本量减少。 这可能会阻止我们继续进行分析。 而且,从实质的角度来看,我们需要确保丢失的数据过程不存在偏见并掩盖不便的事实。

#missing data total = df_train.isnull().sum().sort_values(ascending=False) percent = (df_train.isnull().sum()/df_train.isnull().count()).sort_values(ascending=False) missing_data = pd.concat([total, percent], axis=1, keys=[Total, Percent]) missing_data.head(20)TotalPercentPoolQC14530.995205MiscFeature14060.963014Alley13690.937671Fence11790.807534FireplaceQu6900.472603LotFrontage2590.177397GarageCond810.055479GarageType810.055479GarageYrBlt810.055479GarageFinish810.055479GarageQual810.055479BsmtExposure380.026027BsmtFinType2380.026027BsmtFinType1370.025342BsmtCond370.025342BsmtQual370.025342MasVnrArea80.005479MasVnrType80.005479Electrical10.000685Utilities00.000000

让我们对其进行分析,以了解如何处理丢失的数据。

我们将考虑到,当丢失超过15%的数据时,我们应该删除相应的变量并假装它不存在。这意味着在这种情况下,我们不会尝试任何技巧来填充丢失的数据。据此,我们应删除一组变量(例如“ PoolQC”,“ MiscFeature”,“ Alley”等)。关键是:我们会错过这些数据吗?我不这么认为。这些变量似乎都不是很重要,因为大多数都不是我们在购买房屋时要考虑的方面(也许这就是数据丢失的原因?)。此外,仔细观察变量,我们可以说PoolQC,MiscFeature和FireplaceQu之类的特征是异常值的强力候选者,因此我们很乐意将其删除。

在剩下的情况下,我们可以看到“ Garage”系列特征具有相同数量的丢失数据。我敢打赌,缺失的数据指的是同一组观察结果(尽管我不会对其进行检查;这只是5%,我们不应花费时间在这个问题上)。由于有关车库的最重要信息是由“ GarageCars”表示的,并且考虑到我们只是在谈论丢失的数据的5%,因此我将删除提及的“ Garage”系列特征。相同的逻辑适用于“ Bsmt”系列特征。关于“ MasVnrArea”和“ MasVnrType”,我们可以认为这些特征不是必需的。此外,它们与已经考虑的“ YearBuilt”和“ OverallQual”有很强的相关性。因此,如果删除“ MasVnrArea”和“ MasVnrType”,我们将不会丢失信息。

最后,我们在“Electrical”中有一条缺失的数据。由于这只是一条数据,因此我们将删除该条数据并保留特征。

总之,要处理丢失的数据,我们将删除所有带有缺失数据的变量。

#dealing with missing data df_train = df_train.drop((missing_data[missing_data[Total] > 1]).index,1) df_train = df_train.drop(df_train.loc[df_train[Electrical].isnull()].index) df_train.isnull().sum().max() #just checking that theres no missing data missing... 0

离群值

离群值也是我们应注意的事情。 为什么? 因为离群值会明显影响我们的模型,并且会成为有价值的信息来源,从而为我们提供了有关特定行为的见解。

离群值是一个复杂的主题,应引起更多关注。 在这里,我们将通过“ SalePrice”的标准偏差和一组散点图进行快速分析。

单变量分析

这里主要关注的是建立一个将观察值定义为异常值的阈值。 为此,我们将对数据进行标准化。 在这种情况下,数据标准化意味着将数据值转换为均值为0且标准差为1。

#standardizing data saleprice_scaled = StandardScaler().fit_transform(df_train[SalePrice][:,np.newaxis]); low_range = saleprice_scaled[saleprice_scaled[:,0].argsort()][:10] high_range= saleprice_scaled[saleprice_scaled[:,0].argsort()][-10:] print(outer range (low) of the distribution:) print(low_range) print(\nouter range (high) of the distribution:) print(high_range) outer range (low) of the distribution: [[-1.83820775] [-1.83303414] [-1.80044422] [-1.78282123] [-1.77400974] [-1.62295562] [-1.6166617 ] [-1.58519209] [-1.58519209] [-1.57269236]] outer range (high) of the distribution: [[3.82758058] [4.0395221 ] [4.49473628] [4.70872962] [4.728631 ] [5.06034585] [5.42191907] [5.58987866] [7.10041987] [7.22629831]]

根据上述数据:

低范围值相似,并且离0不太远。高范围值距离0远,而 7.x 值确实超出范围。

目前,我们不会将这些值中的任何一个视为异常值,但应谨慎使用这两个 7.x 值。

双变量分析

我们已经了解了以下散点图。 但是,当我们从新的角度看待事物时,总会有发现的地方。

#bivariate analysis saleprice/grlivarea var = GrLivArea data = pd.concat([df_train[SalePrice], df_train[var]], axis=1) data.plot.scatter(x=var, y=SalePrice, ylim=(0,800000));

发现了什么

带有更大“ GrLivArea”的两个值似乎很奇怪,并且它们并未跟随人群。 我们可以推测为什么会这样。 也许他们指的是农用宅基地,这可以解释价格低廉的原因。 我对此不确定,但我很有信心,这两点不能代表典型案例。 因此,我们将它们定义为离群值并将其删除。图顶部的两个观测值是我们应注意的7.x 观测值。 它们看起来像两种特殊情况,但是它们似乎在追随潮流。 因此,我们将保留它们。#deleting points df_train.sort_values(by = GrLivArea, ascending = False)[:2] df_train = df_train.drop(df_train[df_train[Id] == 1299].index) df_train = df_train.drop(df_train[df_train[Id] == 524].index)#bivariate analysis saleprice/grlivarea var = TotalBsmtSF data = pd.concat([df_train[SalePrice], df_train[var]], axis=1) data.plot.scatter(x=var, y=SalePrice, ylim=(0,800000));

我们可能会想消除一些观察结果(例如TotalBsmtSF> 3000),但我认为这样做是不值得的。 我们可以忍受,所以我们什么也不会做。

这个步骤就是依据业务知识、尝试等除去离群值。

测试基本统计假设

这个问题的答案在于测试多变量分析的统计基础所基于的假设。我们已经进行了一些数据清理,并发现了很多有关“ SalePrice”的信息。现在是时候深入了解“ SalePrice”如何符合统计假设,这使我们能够应用多元数据分析技术。

应检验四个假设:

正态性-当谈论正态性时,我们的意思是数据应该看起来像正态分布。这很重要,因为几个统计检验都依赖于此(例如t统计)。在本练习中,我们将仅检查“ SalePrice”的单变量正态性(这是一种有限的方法)。请记住,单变量正态性不能确保多元正态性(这是我们希望拥有的),但可以提供帮助。要考虑的另一个细节是,在大样本(> 200个观察值)中,正态性不是问题。但是,如果我们解决正态性,就可以避免很多其他问题(例如,异方差性),这就是我们进行此分析的主要原因。关于异方差性,参考:https://baike.baidu.com/item/%E5%BC%82%E6%96%B9%E5%B7%AE%E6%80%A7/3206526?fr=aladdin#2_3同方性-我只是希望我写对了。同方性是指“假设因变量在预测变量范围内表现出相等的方差水平”(Hair et al., 2013)。同质性是可取的,因为我们希望误差项在自变量的所有值上都相同。线性-评估线性的最常见方法是检查散点图并搜索线性模式。如果模式不是线性的,则值得探索数据转换。但是,由于我们所看到的大多数散点图似乎都具有线性关系,因此我们不会对此进行讨论。缺少相关误差-如定义所暗示的,相关误差发生在一个误差与另一个误差相关时。例如,如果一个正误差系统地产生一个负误差,则意味着这些变量之间存在关系。这通常发生在时间序列中,其中某些模式与时间相关。我们也不会涉及到这一点。但是,如果检测到某些东西,请尝试添加一个变量,该变量可以解释您所获得的效果。这是相关误差的最常见解决方案。

寻找正态性

这里的重点是要以非常精简的方式测试“ SalePrice”。 我们将注意以下事项:

直方图-峰度和偏度。正态概率图-数据分布应紧跟代表正态分布的对角线。#histogram and normal probability plot sns.distplot(df_train[SalePrice], fit=norm); fig = plt.figure() res = stats.probplot(df_train[SalePrice], plot=plt)

好的,“ SalePrice”是不遵循正态分布。 它显示“峰值”,正偏度,并且不遵循对角线。

但是,一切并没有丢失。 简单的数据转换可以解决问题。 这是您可以在统计书籍中学到的很棒的东西之一:如果出现正偏斜,对数转换通常效果很好。

#applying log transformation df_train[SalePrice] = np.log(df_train[SalePrice]) #transformed histogram and normal probability plot sns.distplot(df_train[SalePrice], fit=norm); fig = plt.figure() res = stats.probplot(df_train[SalePrice], plot=plt)

Done! 让我们检查一下GrLivArea

#histogram and normal probability plot sns.distplot(df_train[GrLivArea], fit=norm); fig = plt.figure() res = stats.probplot(df_train[GrLivArea], plot=plt)#data transformation df_train[GrLivArea] = np.log(df_train[GrLivArea])

做同样的转换

#transformed histogram and normal probability plot sns.distplot(df_train[GrLivArea], fit=norm); fig = plt.figure() res = stats.probplot(df_train[GrLivArea], plot=plt)

接下来是TotalBsmtSF

#histogram and normal probability plot sns.distplot(df_train[TotalBsmtSF], fit=norm); fig = plt.figure() res = stats.probplot(df_train[TotalBsmtSF], plot=plt)

总结

总的来说,有些东西偏斜。大量值为零的观测值(无地下室的房屋)。一个大问题是因为值零不允许我们进行对数转换。

要在此处应用对数转换,我们将创建一个变量,该变量可以具有或不具有地下室的效果(二进制变量)。 然后,我们将对所有非零观测值进行对数转换,而忽略那些值为零的观测值。 这样,我们可以转换数据,而不会失去具有或不具有地下室的影响。我不确定这种方法是否正确。 在我看来,这似乎是正确的。 这就是我所说的“高风险工程”。

#create column for new variable (one is enough because its a binary categorical feature) #if area>0 it gets 1, for area==0 it gets 0 df_train[HasBsmt] = pd.Series(len(df_train[TotalBsmtSF]), index=df_train.index) df_train[HasBsmt] = 0 df_train.loc[df_train[TotalBsmtSF]>0,HasBsmt] = 1 #transform data df_train.loc[df_train[HasBsmt]==1,TotalBsmtSF] = np.log(df_train[TotalBsmtSF]) #histogram and normal probability plot sns.distplot(df_train[df_train[TotalBsmtSF]>0][TotalBsmtSF], fit=norm); fig = plt.figure() res = stats.probplot(df_train[df_train[TotalBsmtSF]>0][TotalBsmtSF], plot=plt)

尝试寻找“同质性”

测试两个度量变量的均方差的最佳方法是图形化。 通过圆锥(在图形的一侧较小的色散,在相反侧的较大色散)或菱形(分布的中心处有大量点)来表示偏离均等色散的形状。

从“ SalePrice”和“ GrLivArea”开始...

#scatter plot plt.scatter(df_train[GrLivArea], df_train[SalePrice]);

此散点图的较旧版本(在对数转换之前)具有圆锥形状(返回并检查“SalePrice和相关变量之间的散点图“)。 如您所见,当前散点图不再具有圆锥形状。 仅通过确保某些变量的正态性,我们就解决了均方差问题。

现在,让我们用“ TotalBsmtSF”检查“ SalePrice”。

#scatter plot plt.scatter(df_train[df_train[TotalBsmtSF]>0][TotalBsmtSF], df_train[df_train[TotalBsmtSF]>0][SalePrice]);

可以说,通常,“ SalePrice”在“ TotalBsmtSF”的整个范围内均表现出相同的方差水平。

最后但并非最不重要的虚拟变量

#convert categorical variable into dummy df_train = pd.get_dummies(df_train)

关于探索性数据分析的结论

该过程是必要的,原因如下

判断数据特征是否可以用来预测。解决数据正态性问题,就可以避免很多其他问题(例如,异方差性),有助于提高预测的准确性。找到高度相关的维度之间的相关关系。例如,有高度共线关系的维度,就可以去掉其中一个“孪生兄弟”。检查是否有变量随时间变化而周期变化,进而判断是否使用时序列模型。检查数据的缺失情况和异常值。

以上,我们对变量进行了分析与思考,仅对“ SalePrice”进行了分析,并使用了相关性最高的变量,处理了缺失的数据和异常值,测试了一些基本的统计假设,甚至将分类变量转换为虚拟变量。 Python帮助我们简化了很多工作。接下来将开始对数据的标准化和模型的训练与检验,让我们拭目以待,我会在下一篇文章中继续讲解这些过程。

感谢您的阅读。

搜索