用Python分析波士頓的房?jī)r(jià),酸爽!!!

這個(gè)是Kaggle專欄的第二篇,賽題名是:House Prices - Advanced Regression Techniques。在本文中你將會(huì)學(xué)習(xí)到:
單、多變量分析 相關(guān)性分析 缺失值和異常值處理 啞變量轉(zhuǎn)換

原notebook地址:
https://www.kaggle.com/pmarcelino/comprehensive-data-exploration-with-python
一、排名榜
讓我們看下排名榜,第一名真的是碾壓其他選手呀~所以,今天我們一起看看這個(gè)第一名的方案到底是多棒?

二、數(shù)據(jù)介紹
這份波士頓房?jī)r(jià)的數(shù)據(jù)集有4份數(shù)據(jù),訓(xùn)練集train+測(cè)試集test+數(shù)據(jù)集的描述description+提交模板sample

其中訓(xùn)練集有81個(gè)特征,1460條數(shù)據(jù);測(cè)試集81個(gè)特征,1459條數(shù)據(jù)。看下部分屬性介紹:


三、數(shù)據(jù)EDA
導(dǎo)入模塊和數(shù)據(jù),并進(jìn)行數(shù)據(jù)探索:
導(dǎo)入庫(kù)
import?pandas?as?pd
import?numpy?as?np
#?繪圖相關(guān)
import?plotly.express?as?px
import?matplotlib.pyplot?as?plt
import?seaborn?as?sns
plt.style.use("fivethirtyeight")
#?數(shù)據(jù)建模
from?scipy.stats?import?norm
from?scipy?import?stats
from?sklearn.preprocessing?import?StandardScaler
#?警告
import?warnings
warnings.filterwarnings('ignore')
%matplotlib?inline
導(dǎo)入數(shù)據(jù)

數(shù)據(jù)信息
訓(xùn)練集整體是1460*81;而且很多的存在字段都存在缺失值

描述統(tǒng)計(jì)信息:

四、銷售價(jià)格SalePrice分析
原notebook文檔中,作者分析了很多自己關(guān)于這個(gè)題目和字段的看法,具體不闡述。下面介紹的是重點(diǎn)部分:
統(tǒng)計(jì)信息
單單看這個(gè)字段的統(tǒng)計(jì)信息:

分布直方圖如下,我們明顯感受到:
價(jià)格的分布偏離了正態(tài)分布 有明顯的正偏度現(xiàn)象 有明顯的峰值出現(xiàn)

偏度和峰度(skewness and kurtosis)
知識(shí)加油站:偏度和峰度
詳細(xì)的解釋參見文章:https://zhuanlan.zhihu.com/p/53184516
偏度:衡量隨機(jī)變臉概率分布的不對(duì)稱性,是相對(duì)于平均值不對(duì)稱程度的度量,通過對(duì)偏度系數(shù)的測(cè)量,我們能夠判定數(shù)據(jù)分布的不對(duì)稱程度以及方向。 峰度:是研究數(shù)據(jù)分布陡峭或者平滑的統(tǒng)計(jì)量,通過對(duì)峰度系數(shù)的測(cè)量,我們能夠判定數(shù)據(jù)相對(duì)于正態(tài)分布而言是更陡峭還是更平緩。峰度接近0,數(shù)據(jù)呈現(xiàn)正態(tài)分布;峰度>0,高尖分布;峰度<0,矮胖分布
偏度的兩種分布情況:
如果是左偏,則偏度小于0 如果是右偏,則偏度大于0

峰度的兩種分布情況:
如果是高瘦型,則峰度大于0 如果是矮胖型,則峰度小于0

#?打印銷售價(jià)格的偏度和峰度
print("Skewness(偏度):?%f"?%?train['SalePrice'].skew())
print("Kurtosis(峰度):?%f"?%?train['SalePrice'].kurt())
Skewness(偏度):?1.882876
Kurtosis(峰度):?6.536282
偏度和峰度值都是正的,明顯說明數(shù)據(jù)是右偏且高尖分布
SalePrice和數(shù)值型字段的關(guān)系
首先我們考察和居住面積的關(guān)系:

plt.figure(1,figsize=(12,6))
sns.scatterplot(x="GrLivArea",y="SalePrice",data=data)
plt.show()

#?plotly版本
px.scatter(data,x="GrLivArea",y="SalePrice",trendline="ols")

TotalBsmtSF VS SalePrice
#?2、TotalBsmtSF?
data?=?train[["SalePrice","TotalBsmtSF"]]
plt.figure(1,figsize=(12,6))
sns.scatterplot(x="TotalBsmtSF",y="SalePrice",data=data)
plt.show()

小結(jié):我們可以觀察到這兩個(gè)特征和銷售價(jià)格之間是存在一定的線性關(guān)系。
價(jià)格和分類型字段的關(guān)系
1、OverallQual VS SalePrice
# 1、OverallQual:整體房屋質(zhì)量
#?總共10個(gè)類別
train["OverallQual"].value_counts()
5?????397
6?????374
7?????319
8?????168
4?????116
9??????43
3??????20
10?????18
2???????3
1???????2
Name:?OverallQual,?dtype:?int64
data?=?train[["SalePrice","OverallQual"]]
#?房屋整體質(zhì)量和房?jī)r(jià)的關(guān)系
#?繪制子圖:1號(hào)位
f,ax?=?plt.subplots(1,figsize=(12,6))
fig?=?sns.boxplot(x="OverallQual",y="SalePrice",data=data)
#?y軸的刻度范圍
fig.axis(ymin=0,ymax=800000)
plt.show()

2、YearBuilt VS SalePrice
住宅建造年份和銷售價(jià)格的關(guān)系
data?=?train[["SalePrice","YearBuilt"]]
#?建造年份和房?jī)r(jià)的關(guān)系
f,ax?=?plt.subplots(1,figsize=(16,8))
fig?=?sns.boxplot(x="YearBuilt",y="SalePrice",data=data)
#?y軸的刻度范圍
fig.axis(ymin=0,ymax=800000)
plt.show()

小結(jié):銷售價(jià)格和住宅的整體質(zhì)量有很強(qiáng)的關(guān)系;但是和建筑年份的關(guān)系不大。但是在實(shí)際的買房過程中,我們還是會(huì)很在意年份
小結(jié)
對(duì)上面分析的一點(diǎn)小結(jié):
地面生活區(qū)(GrLivArea)、地下室面積(GrLivArea)和銷售價(jià)格SalePrice都是呈現(xiàn)正向的線性相關(guān) 房屋的整體質(zhì)量(OverallQual)和建造年份(YearBuilt)好像也和銷售價(jià)格線性相關(guān)。常識(shí)來說,整體的質(zhì)量越好,價(jià)格越貴
五、相關(guān)性分析
為了探索眾多屬性之間的關(guān)系,進(jìn)行如下的分析:
兩兩屬性間的相關(guān)性(熱力圖) 銷售價(jià)格saleprice和其他屬性的關(guān)系(熱力圖) 關(guān)聯(lián)性最大的屬性間的關(guān)系(散點(diǎn)圖)
整體相關(guān)性
分析每?jī)蓚€(gè)屬性的相關(guān)性,并繪制熱力圖


上圖中有兩個(gè)值得關(guān)注的點(diǎn):
TotalBsmtSF and 1stFlrSF GarageCar and GarageArea
這兩組變量都是強(qiáng)相關(guān)的,我們后續(xù)的分析只取其中一個(gè)
縮放相關(guān)矩陣(銷售價(jià)格saleprice)
從上面的熱力圖中選擇和SalePrice相關(guān)性最強(qiáng)的前10個(gè)特征來繪制熱力圖


sns.set(font_scale=1.25)
hm?=?sns.heatmap(
????cm,??#?繪圖數(shù)據(jù)
????cbar=True,??#?是否將顏色條作為圖例,默認(rèn)True
????annot=True,??#?是否顯示數(shù)值
????square=True,??#?是否使熱力圖每個(gè)單元為正方形,默認(rèn)為False
????fmt='.2f',??#?保留兩位小數(shù)
????annot_kws={'size':10},
????xticklabels=cols.values,?#?xy軸設(shè)置
????yticklabels=cols.values)
plt.show()

小結(jié)1
通過上面的縮放熱力圖,我們可以得到下面的結(jié)論:
'OverallQual', 'GrLivArea' and 'TotalBsmtSF'是真的和'SalePrice'呈現(xiàn)強(qiáng)相關(guān) 'GarageCars' and 'GarageArea' 也是兩個(gè)相關(guān)性比較強(qiáng)的特征;而且他們都是同時(shí)出現(xiàn),后續(xù)選取GarageCars進(jìn)行分析 建筑年限'YearBuilt'相對(duì)來說,相關(guān)性比較低
變量離散圖
將銷售價(jià)格SalePrice和幾個(gè)相關(guān)性比較強(qiáng)的特征放在一起,繪制變量離散圖
sns.set()
#?待分析的變量
cols?=?['SalePrice',?'OverallQual',?'GrLivArea',?'GarageCars',?'TotalBsmtSF',?'FullBath',?'YearBuilt']
sns.pairplot(train[cols],size=2.5)
plt.show()

小結(jié)2
正對(duì)角線方向上是變量的直方圖,解釋變量和被解釋變量SalePrice,其他的則是散點(diǎn)圖。
如果圖中呈現(xiàn)直線或者橫線的散點(diǎn),則說明該變量是離散的,比如第1行4列的變量,y軸是SalePrice,x軸是YearBuilt,直線說明YearBuilt是離散的
六、缺失值處理
針對(duì)缺失值的情況,主要是討論兩點(diǎn):
缺失值分布情況怎么樣? 缺失值是隨機(jī)的?還有具有某種規(guī)律
缺失值占比
1、查看每個(gè)字段的缺失值情況
#?每個(gè)字段的缺失值數(shù)量:降序
total?=?train.isnull().sum().sort_values(ascending=False)
total.head()
PoolQC?????????1453
MiscFeature????1406
Alley??????????1369
Fence??????????1179
FireplaceQu?????690
dtype:?int64
2、轉(zhuǎn)成百分比
#?每個(gè)字段的缺失值?/?總數(shù)
percent?=?(train.isnull().sum()?/?train.isnull().count()).sort_values(ascending=False)
percent.head()
PoolQC?????????0.995205
MiscFeature????0.963014
Alley??????????0.937671
Fence??????????0.807534
FireplaceQu????0.472603
dtype:?float64
3、數(shù)據(jù)合并,整體的缺失值情況:

刪除缺失值
原文中分析了很多,最后的結(jié)論:
In summary, to handle missing data,
1、we'll delete all the variables with missing data, except the variable 'Electrical'.
2、In 'Electrical' we'll just delete the observation with missing data.
#?步驟1:需要?jiǎng)h除的字段
missing_data[missing_data["Total"]?>?1].index
Index(['PoolQC',?'MiscFeature',?'Alley',?'Fence',?'FireplaceQu',?'LotFrontage',
???????'GarageYrBlt',?'GarageCond',?'GarageType',?'GarageFinish',?'GarageQual',
???????'BsmtFinType2',?'BsmtExposure',?'BsmtQual',?'BsmtCond',?'BsmtFinType1',
???????'MasVnrArea',?'MasVnrType'],
??????dtype='object')
#?第一步
train?=?train.drop(missing_data[missing_data["Total"]?>?1].index,1)
#?第二步
train?=?train.drop(train.loc[train["Electrical"].isnull()].index)

七、離群點(diǎn)out liars
查找離群點(diǎn)
##?數(shù)據(jù)標(biāo)準(zhǔn)化standardizing?data
#?np.newaxis?增加數(shù)據(jù)維度,一維變成二維
saleprice_scaled?=?StandardScaler().fit_transform(train["SalePrice"][:,np.newaxis])
saleprice_scaled[:5]
array([[?0.34704187],
???????[?0.0071701?],
???????[?0.53585953],
???????[-0.5152254?],
???????[?0.86943738]])
#?查看前10和最后10位的數(shù)據(jù)
# argsort:返回的是索引值;默認(rèn)是升序排列,最小的在最前面,最大的在最后
low_range?=?saleprice_scaled[saleprice_scaled[:,0].argsort()][:10]
high_range?=?saleprice_scaled[saleprice_scaled[:,0].argsort()][-10:]
print(low_range)
print('----------')
print(high_range)

小結(jié)3
low_range接近,且離0比較近 high_range離0很遠(yuǎn);且7+的數(shù)據(jù)就應(yīng)該是離群點(diǎn)了
單變量分析1
data?=?train[["SalePrice","GrLivArea"]]
data.plot.scatter(x="GrLivArea",y="SalePrice",ylim=(0,800000))
plt.show()

很明顯的,兩個(gè)變量(屬性)存在一種線性關(guān)系
刪除離群點(diǎn)
指定刪除某個(gè)字段為具體值的方法:

單變量分析2
data?=?train[["SalePrice","TotalBsmtSF"]]???#?待分析的兩個(gè)變量
data.plot.scatter(x="TotalBsmtSF",y="SalePrice",ylim=(0,800000))
plt.show()

八、深入理解SalePrice
主要從以下幾個(gè)方面來深入研究銷售價(jià)格:
Normality:歸一化 Homoscedasticity:同方差性 Linearity:線性特質(zhì) Absence of correlated errors:相關(guān)誤差
Normality歸一化(SalePrice)
sns.distplot(train["SalePrice"],fit=norm)
fig?=?plt.figure()
res?=?stats.probplot(train["SalePrice"],?plot=plt)

我們發(fā)現(xiàn):銷售價(jià)格不是正態(tài)分布的,出現(xiàn)了右偏度;同時(shí)也不遵循對(duì)數(shù)變化的規(guī)律。
為了解決這個(gè)問題:實(shí)施對(duì)數(shù)變換
##?對(duì)數(shù)變換
train["SalePrice"]?=?np.log(train["SalePrice"])
sns.distplot(train["SalePrice"],fit=norm)
fig?=?plt.figure()
res?=?stats.probplot(train["SalePrice"],?plot=plt)

實(shí)施對(duì)數(shù)變換后效果好了很多的
Normality-歸一化(GrLivArea)
sns.distplot(train["GrLivArea"],fit=norm)
fig?=?plt.figure()
res?=?stats.probplot(train["GrLivArea"],?plot=plt)
對(duì)數(shù)變換前的效果:

執(zhí)行對(duì)數(shù)變換及效果:
#?執(zhí)行相同的對(duì)數(shù)操作
train["GrLivArea"]?=?np.log(train["GrLivArea"])
sns.distplot(train["GrLivArea"],fit=norm)
fig?=?plt.figure()
res?=?stats.probplot(train["GrLivArea"],?plot=plt)

Normality-歸一化(TotalBsmtSF)
sns.distplot(train["TotalBsmtSF"],fit=norm)
fig?=?plt.figure()
res?=?stats.probplot(train["TotalBsmtSF"],?plot=plt)
處理之前的效果:

如何處理上面的特殊部分?
#?增加一列數(shù)據(jù)
train['HasBsmt']?=?0
#?當(dāng)TotalBsmtSF>0?則賦值1
train.loc[train['TotalBsmtSF']>0,'HasBsmt']?=?1
#?對(duì)數(shù)轉(zhuǎn)換:等于1的部分
train.loc[train['HasBsmt']==1,'TotalBsmtSF']?=?np.log(train['TotalBsmtSF'])
#?繪圖
data?=?train[train['TotalBsmtSF']>0]['TotalBsmtSF']
sns.distplot(data,fit=norm)
fig?=?plt.figure()
res?=?stats.probplot(data,?plot=plt)

九、同方差性
檢驗(yàn)兩個(gè)變量之間的同方差性最好的方法就是作圖。
The best approach to test homoscedasticity for two metric variables is graphically
1、討論:'SalePrice' 和'GrLivArea'之間的關(guān)系

2、討論SalePrice' 和 'TotalBsmtSF'

We can say that, in general, 'SalePrice' exhibit equal levels of variance across the range of 'TotalBsmtSF'. Cool!
從上面的兩張圖中,我們看到:銷售價(jià)格和另外兩個(gè)變量都是呈現(xiàn)一定的正向關(guān)系
十、生成啞變量
虛擬變量( Dummy Variables) 又稱虛設(shè)變量、名義變量或啞變量,用以反映質(zhì)的屬性的一個(gè)人工變量,是量化了的自變量,通常取值為0或1。
Pandas中的get_dummies函數(shù)能夠?qū)崿F(xiàn):
train?=?pd.get_dummies(train)??#?生成啞變量
train

十一、總結(jié)
至此,我們完成了以下的內(nèi)容:
整體變量間的相關(guān)性分析 重點(diǎn)分析了變量“SalePrice” 處理缺失值和異常值(離群點(diǎn)) 做了一些統(tǒng)計(jì)分析,將分類變量變成了啞變量
自己需要后續(xù)補(bǔ)充深入學(xué)習(xí)的點(diǎn):
多元統(tǒng)計(jì)分析 偏度和峰度 啞變量的深入 標(biāo)準(zhǔn)化和歸一化
推薦閱讀:
入門:?最全的零基礎(chǔ)學(xué)Python的問題? |?零基礎(chǔ)學(xué)了8個(gè)月的Python??|?實(shí)戰(zhàn)項(xiàng)目?|學(xué)Python就是這條捷徑
量化:?定投基金到底能賺多少錢?? |?我用Python對(duì)去年800只基金的數(shù)據(jù)分析??
干貨:爬取豆瓣短評(píng),電影《后來的我們》?|?38年NBA最佳球員分析?|? ?從萬(wàn)眾期待到口碑撲街!唐探3令人失望? |?笑看新倚天屠龍記?|?燈謎答題王?|用Python做個(gè)海量小姐姐素描圖?|碟中諜這么火,我用機(jī)器學(xué)習(xí)做個(gè)迷你推薦系統(tǒng)電影
趣味:彈球游戲? |?九宮格? |?漂亮的花?|?兩百行Python《天天酷跑》游戲!
AI:?會(huì)做詩(shī)的機(jī)器人?|?給圖片上色?|?預(yù)測(cè)收入?|?碟中諜這么火,我用機(jī)器學(xué)習(xí)做個(gè)迷你推薦系統(tǒng)電影
小工具:?Pdf轉(zhuǎn)Word,輕松搞定表格和水印!?|?一鍵把html網(wǎng)頁(yè)保存為pdf!|??再見PDF提取收費(fèi)!?|?用90行代碼打造最強(qiáng)PDF轉(zhuǎn)換器,word、PPT、excel、markdown、html一鍵轉(zhuǎn)換?|?制作一款釘釘?shù)蛢r(jià)機(jī)票提示器!?|60行代碼做了一個(gè)語(yǔ)音壁紙切換器天天看小姐姐!|

