基于python的智能房价系统_利用Python进行探索性数据分析:基于房价数据

认识自己是最困难的事情。

在数据科学中,最困难的是就是了解数据本身。这是最耗费时间和精力的部分,也是最容易被忽视的第一步。

本例将试图就走好这第一步,归纳出在探索性分布中具有意义的分析原则。

本例的分析将从以下几个方面推进:

1.理解问题。首先,我们将审视每一个变量,并探讨其对于解决最终问题的意义。

2.单变量分析。围绕应变量(SalePrice),我们将试图了解其影响因素。

3.多变量分析。这里将建立自变量和应变量之间的关系。

4.数据清理。这里将清理数据集,处理缺失值、异常值和分类变量。

5.假设检验。这里对数据分布进行检验,观察是否符合假设检验的前提,为下一步分布做准备。

1.分析前的准备

载入分析包和数据

# 载入分析包

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('D:/MY & Research/MY/4.Data Analysis & Visualization/4.Python/1.House Prices/data/train.csv')

# 查看变量

df_train.columns

Index(['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')

2.观察变量

概览变量,我们需要注意以下几点:变量存在两种类型:数值和类别;

根据变量的特性,可将其划分类别,例如地理位置、空间、房屋质量情况等;

需要预测分析的变量是“saleprice”;

最终结论应该是分析哪些变量对价格的影响更大;

概览变量之后,我们应该问自己几个问题:当我们自己去买房子的时候,我们关注哪些因素?

在那些因素中,那种最为重要?

我们关注的这些因素是否存在于数据集中的变量中?

所以,可能并不是所有的变量都需要分析。总体来看,影响较大的变量主要有:OverallQual, YearBuil, TotalBsmtSF, GrliveArea

3.分析应变量: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

可以发现,saleprice最小值是大于0的,这意味我们之前的假设是合理的。

# 绘制直方图

sns.distplot(df_train['SalePrice'], color = "g")

可以发现房价变量是很明显非正态分布。

4.简要分析SalePrice与几个变量之间关系

根据之前的分析,我们预计OverallQual, YearBuil, TotalBsmtSF, GrliveArea这四个变量与SalePrice之间相关性更强。

我么仍然需要注意:OverallQual和YearBuit是分类变量,TotalBsmtSF和GrliveArea是数值型变量。这决定我们要采用不同分析技术。

4.1 SalePrice 和 OverallQual

data = pd.concat([df_train['SalePrice'], df_train['OverallQual']], axis = 1)

f, ax = plt.subplots(figsize = (8, 6))

fig = sns.boxplot(x = 'OverallQual', y = "SalePrice", data = data)

fig.axis(ymin = 0, ymax = 800000)

(-0.5, 9.5, 0, 800000)

相关性相对还是较强的。

4.2 SalePrice 和 YearBuilt

data = pd.concat([df_train['SalePrice'], df_train['YearBuilt']], axis = 1)

f, ax = plt.subplots(figsize = (16, 8))

fig = sns.boxplot(x = 'YearBuilt', y = "SalePrice", data = data)

fig.axis(ymin = 0, ymax = 800000)

plt.xticks(rotation = 90)

(array([ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12,

13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25,

26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38,

39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51,

52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64,

65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77,

78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90,

91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103,

104, 105, 106, 107, 108, 109, 110, 111]),

)

相关性看起来并没有那么绝对,但是我们仍然可以得出结论:相比较于建造年代较远的房子,新建造的房子更能获得更高的报价。

4.3 SalePrice 和 TotalBsmtSF

data = pd.concat([df_train['SalePrice'], df_train['TotalBsmtSF']], axis = 1)

data.plot.scatter(x = 'TotalBsmtSF', y = 'SalePrice', ylim = (0,800000))

明显的线性相关。

4.4 SalePrice 和 GrLivArea

data = pd.concat([df_train['SalePrice'], df_train['GrLivArea']], axis = 1)

data.plot.scatter(x = 'GrLivArea', y = 'SalePrice', ylim = (0,800000))

明显的线性相关。

小结:GrLivArea 和 TotalBsmtSF 与 SalePrice 存在明显的正相关关系,即一方增加另一方也增加。同时,相比较于GrLivArea,TotalBsmtSF的斜率更大。

OverallQual 和 YearBuilt 与 SalePrice 也存在相关性,而且OverllQual的相关性更大。

这是几个看起来影响最大的四个因素,仍然存在许多其他变量有待分析。

5.观察其他变量

为了观察其他变量的影响,我们需要借助以下几个分析技术:相关矩阵(热力图);

SalePrice 相关矩阵;

SalePrice与相关较强的变量之间的数据分布;

5.1 相关矩阵

corrmat = df_train.corr()

f, ax = plt.subplots(figsize = (23, 9))

sns.heatmap(corrmat, vmax=0.8, square = True)

热力图是快速了解变量之间关系最简便的方式。 通过热力图,我们首先就能发现两点值得关注:

1.TotalBsmtSF 和 1stFlrSF;

2.GarageCare 和 GarageArea;

这两组变量相关性如此之强,以致于我们不得不考虑多重共线性,即他们提供了相同的信息。这也正式热力图的强项所在。

此外,在SalePrice列中,除了已经分析四个变量,仍然有许多其他变量与其有较强的相关性。这也正是下一步分析的重点。

5.2 SalePrice相关矩阵

k = 10

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 = '0.2f',

annot_kws = {'size':10}, yticklabels = cols.values,

xticklabels = cols.values)

plt.show()

因此,我们可以总结:OverallQual、GrLivArea和TotalBsmtSF相关最强;

GarageCars与GarageArea两者之间相关性较强,因此保留其中一个分析即可。考虑到,GarageCars与SalePrice的相关性更强,保留GarageCars;

对于TotalBsmtSF 和 1stFlrSF,考虑到我们最初的假设,保留前者;

TotRmsAbvGrd和GrLivArea两者之间也存在较强相关性,待察;

FullBath,待察;

YearBuilt与SalePrice的相关性并没有特别的强,待察。

5.3 SalePrice与相关较强的变量之间的数据分布;

sns.set()

cols = ['SalePrice', 'OverallQual', 'GrLivArea', 'GarageCars', 'TotalBsmtSF', 'FullBath', 'YearBuilt']

sns.pairplot(df_train[cols], size = 2.5)

plt.show();

6.处理缺失值

在处理缺失值之前有必要思考两个问题:缺失值的数量;

缺失值的分布情况:随机还是存在某种规律。

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)

我们可以给自己设定一个标准,即当某个变量15%的数据是缺失的时候,那么我们应该将这个变量排除在分析之内。据此,PoolQC、MiscFeature、Alley、Fence、FireplaceQu、LotFrontage等变量排除。(实际上,根据常理,购房时这些变量确实并不怎么在考虑范围之内。)

我们还可以发现“Garage*”和“BsmtX”两个系列变量的缺失值数量分别一致。我们可以认为这些变量实际上反映了相同的信息。因此,保留其中一个即可。

对于MasVnrArea和MasVnrType,我么认为其不重要。更重要的是,他们与YearBuilt和OverallQual有很强的相关性,排除他们也不会影响最终的分析结果。

最后,对于Electrical,仅有一个缺失值,那么删除这个缺失值而保留这个变量即可。

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() #确认一下是否还存在缺失值

0

7.异常值

异常值会对模型产生强烈影响。这里我们对SalePrice异常值进行一个快速分析。

7.1 基于单个变量的分析

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]]

通过对SalePrice的值进行标准化处理,我们可以发现 :最小那部分值与0的距离并不远;

最大的那部分值与0的距离较远,特别最大的两个值距离达到了7以上,值得关注。

7.2 基于多个变量的分析

7.2.1 GrlLivArea与SalePrice

var = 'GrLivArea'

data = pd.concat([df_train['SalePrice'], df_train[var]], axis=1)

data.plot.scatter(x=var, y='SalePrice', ylim=(0,800000));

'c' argument looks like a single numeric RGB or RGBA sequence, which should be avoided as value-mapping will have precedence in case its length matches with 'x' & 'y'. Please use a 2-D array with a single row if you really want to specify the same RGB or RGBA value for all points.

可以发现:在右下角存在两个偏离整体的异常值,这里将这个异常值的记录删除。

在右上角还存在两个符合整体分布趋势的异常值,即前文提到需要关注的“距离在7以上”的异常值。考虑其符合整体分布趋势,可以将其保留。

# 删除异常值

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)

7.2.2 TotalBsmSF与SalePrice

var = 'TotalBsmtSF'

data = pd.concat([df_train['SalePrice'], df_train[var]], axis=1)

data.plot.scatter(x=var, y='SalePrice', ylim=(0,800000));

'c' argument looks like a single numeric RGB or RGBA sequence, which should be avoided as value-mapping will have precedence in case its length matches with 'x' & 'y'. Please use a 2-D array with a single row if you really want to specify the same RGB or RGBA value for all points.

总体而言,分布基本呈规律,并无需要特别注意的异常值。

8.假设检验

通常假设检验需要满足四个前提假设:Normality

Homoscedasticity

Linearity Absence

of correlated errors

8.1 正态分布

检验是否满足正态分布,通常使用两种图形技术:直方图:观察峰度和偏度;

正态分布概率图:观察变量是否满足正态分布;

8.1.1 SalePrice

sns.distplot(df_train['SalePrice'], fit=norm);

fig = plt.figure()

res = stats.probplot(df_train['SalePrice'], plot=plt)

可以观察到:SalePrice并不满足正态分布。对此,可以采用对数转换来处理。

df_train['SalePrice'] = np.log(df_train['SalePrice'])

sns.distplot(df_train['SalePrice'], fit=norm);

fig = plt.figure()

res = stats.probplot(df_train['SalePrice'], plot=plt)

8.1.2 GrLivArea

sns.distplot(df_train['GrLivArea'], fit=norm);

fig = plt.figure()

res = stats.probplot(df_train['GrLivArea'], plot=plt)

并不满足正态分布,采用对数转换。

df_train['GrLivArea'] = np.log(df_train['GrLivArea'])

sns.distplot(df_train['GrLivArea'], fit=norm);

fig = plt.figure()

res = stats.probplot(df_train['GrLivArea'], plot=plt)

8.1.3 TotalBsmSF

sns.distplot(df_train['TotalBsmtSF'], fit=norm);

fig = plt.figure()

res = stats.probplot(df_train['TotalBsmtSF'], plot=plt)

可以观察到,TotalBsmtSF的分布是很明显的非正态:偏度很大;

正态分布概率图中有很多观察值为“0”的情况;

这意味者将无法进行对数转换。

对此,我们采用以下方法进行转换:创建一个虚拟变量;

对取值非零的做对数化处理;

# 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

# 转换数据

df_train.loc[df_train['HasBsmt']==1,'TotalBsmtSF'] = np.log(df_train['TotalBsmtSF'])

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)

8.2 方差齐性

8.2.1 GrLiveArea 和 SalePrice

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

与之前的相比,这里分布不再类似一个圆锥形。

8.2.2 TotalBsmtSF 和 SalePrice

plt.scatter(df_train[df_train['TotalBsmtSF']>0]['TotalBsmtSF'],

df_train[df_train['TotalBsmtSF']>0]['SalePrice']);

9.处理分类变量

将分类变量转换为虚拟变量。

df_train = pd.get_dummies(df_train)

10.小结

探索性分析是数据分析的第一步,也是经常被忽略的关键一步。

本例中,基于房价数据,我们:分析了SalePrice及其相关变量;

处理了缺失值和异常值;

为了为后期的数据预测做准备,对数据分布进行观察,并进行对数化处理;

将分类变量转换为虚拟变量。

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值