1. 案例說明
通過收集相關(guān)網(wǎng)站對酒店評價,poi地理數(shù)據(jù),和酒店自身介紹探索影響酒店入住價格的因素
數(shù)據(jù)來源:狗熊會
2.變量分析探索
#讀取數(shù)據(jù)
import os
os.chdir(r'C:\Users\Administrator\Desktop\狗熊會數(shù)據(jù)\5.1 北京高檔酒店價格分析')
df =pd.read_csv('hoteldata.csv')
#查看數(shù)據(jù)
df.head()
#查看數(shù)據(jù)類型
df.info()
數(shù)據(jù)無缺失值,變量類型正確
#查看描述性統(tǒng)計
df.describe().T
查看酒店價格分布,酒店價格集中在1000-2000元間
未避免殘差異方差,因變量需取對數(shù)
#酒店房價正太轉(zhuǎn)化
df['房價取對數(shù)'] = np.log1p(df['房價'])
df['房價取對數(shù)'].hist(bins=20)
plt.show()
對音箱酒店房價因素的變量進行探索性分布
sns.boxplot(x='房間類型',y='房價取對數(shù)',data=df)
方差分析
import statsmodels.api as sm
from statsmodels.formula.api import ols
ana =ols('房價取對數(shù)~C(房間類型)',data=df).fit()
sm.stats.anova_lm(ana)
F值顯著,房間類型對酒店因素有明顯相關(guān)性
sns.boxplot(x='地區(qū)',y='房價取對數(shù)',data=df)
方差分析
F值不顯著,地區(qū)對酒店因素?zé)o明顯相關(guān)性
sns.scatterplot(x='經(jīng)度',y='緯度',hue='房價取對數(shù)',data=df)
查看酒店經(jīng)緯度散點圖,酒店都集中在市中心,且價格跟市中心距離無太大關(guān)聯(lián),某些酒店遠離市中心但是房價較高,可能為度假區(qū),查看這些數(shù)據(jù)
百度了一下這個酒店,哇~~
3.修改變量
#變量轉(zhuǎn)換
對時間序列變量,轉(zhuǎn)化為連續(xù)變量,將分類變量啞編碼
#時間序列變量處理
df['裝修年限'] = 2018-df['裝修時間']
#對分類變化進行啞變量轉(zhuǎn)換
area = pd.get_dummies(df['地區(qū)'])
#以其他城區(qū)作為基準(zhǔn)組
area.drop('其他城區(qū)',axis=1,inplace=True)
housetype = pd.get_dummies(df['房間類型'])
#以標(biāo)準(zhǔn)間作為基準(zhǔn)組
housetype.drop('標(biāo)準(zhǔn)間',axis=1,inplace=True)
df_model = pd.concat([df,area],axis=1)
df_model = pd.concat([df_model,housetype],axis=1)
相關(guān)性分析
#定義自變量和因變量
#自變量
cols = ['衛(wèi)生評分','服務(wù)評分','設(shè)施評分','位置評分','評價數(shù)','公司','出行住宿','校園生活','裝修年限','東城區(qū)','朝陽區(qū)','海淀區(qū)','商務(wù)間'
,'豪華套間']
#相關(guān)性分析
plt.figure(figsize=(12,9))
sns.heatmap(df_model[cols].corr(),vmax=1,annot=True)
相關(guān)性高于0.6就具有高共線性,需對變量進行剔除,或者變量轉(zhuǎn)化,將評分屬性降維處理,降維為變量'綜合評分'
from sklearn.preprocessing import MinMaxScaler
scaler =MinMaxScaler()
#先將評分屬性進行標(biāo)準(zhǔn)化處理
df_model[['衛(wèi)生評分','服務(wù)評分','設(shè)施評分','位置評分']] = scaler.fit_transform(df_model[['衛(wèi)生評分','服務(wù)評分','設(shè)施評分','位置評分']])
from sklearn.decomposition import PCA
pca = PCA()
pca.fit(df_model[['衛(wèi)生評分','服務(wù)評分','設(shè)施評分','位置評分']])
pca.explained_variance_ratio_
#其中一個變量就能解釋其中90%的變異數(shù)據(jù)
pca = PCA(n_components=1)
df_model['綜合評分'] = pca.fit_transform(df_model[['衛(wèi)生評分','服務(wù)評分','設(shè)施評分','位置評分']])
pca.components_
#將公司和出行住宿具有高共線性,將公司變量剔除
cols = ['綜合評分','評價數(shù)','出行住宿','校園生活','裝修年限','東城區(qū)','朝陽區(qū)','海淀區(qū)','商務(wù)間'
,'豪華套間']
4.構(gòu)建模型
不進行變量篩選,構(gòu)建模型
import statsmodels.api as sm
from statsmodels.formula.api import ols
formula = '%s~%s'%('房價取對數(shù)','+'.join(cols))
lm_s = ols(formula,data=df_model).fit()
lm_s.summary()
R方0.58,DW:1.117 (DW接近2,殘差自相關(guān)不存在),模型表現(xiàn)尚可,其中評價數(shù)和裝修年限相關(guān)性不顯著(P值>0.05)
#殘差QQ圖
resid = lm_s.resid
from scipy import stats
fig = plt.figure()
res = stats.probplot(resid,plot=plt) #樣本為Series荤牍,默認dist='norm' 擬合直線為正太分布
對變量進行篩選
#變量篩選,使用向前法,以AIC為標(biāo)準(zhǔn)對變量進行篩選
#定義向前選擇法
import statsmodels.api as sm
from statsmodels.formula.api import ols
def forward_select(data,col,y):
remaining = col
#remaining.remove(y)#定義自變量
selected = []
current_score,best_new_score = float('inf'),float('inf')#定義
while remaining:
aiclst = []
for i in remaining:
formula = '%s~%s'%(y,'+'.join(selected+[i]))
aic = ols(formula=formula,data=data).fit().aic
aiclst.append((aic,i))
aiclst.sort(reverse =True)
best_new_score,best_i = aiclst.pop()#刪除AIC最高的變量,并返回值
if current_score > best_new_score:
remaining.remove(best_i)
selected.append(best_i)
current_score = best_new_score
print('aic is %f,coutinuing'%current_score)
else:
print('forward_select over')
break
return(selected)
cols_fs = forward_select(df_model,cols,'房價取對數(shù)')
篩選后變量為
['綜合評分', '豪華套間', '商務(wù)間', '出行住宿', '校園生活', '海淀區(qū)', '東城區(qū)', '朝陽區(qū)']
構(gòu)建模型
formula = '%s~%s'%('房價取對數(shù)','+'.join(cols_fs))
lm_s1 = ols(formula,data=df_model).fit()
lm_s1.summary()
#殘差QQ圖
resid1 = lm_s1.resid
from scipy import stats
fig = plt.figure()
res = stats.probplot(resid1,plot=plt) #樣本為Series举塔,默認dist='norm' 擬合直線為正太分布
#強影像點分析
from statsmodels.stats.outliers_influence import OLSInfluence
OLSInfluence(lm_s1).summary_frame().head()
#VIF方差分析
from statsmodels.stats.outliers_influence import variance_inflation_factor as vif
for i in range(len(cols_fs)):
print('%s vif: %f' %(cols_fs[i],vif(np.array(df_model[cols_fs]),i)))
#殘差異方差性顯著性
from statsmodels.stats.diagnostic import het_breuschpagan
het = het_breuschpagan(resid1,df_model[cols_fs])
print('p-value: %6.4f'%het[-1])
p-value: 0.0000
模型診斷
殘差不存在異方差性,模型內(nèi)變量VIF 小于10,無多重共線性,COOK距離表現(xiàn)正常,無異常點