多元线性回归 - 北京高档酒店价格影响因素分析

1. 案例说明

通过收集相关网站对酒店评价,poi地理数据,和酒店自身介绍探索影响酒店入住价格的因素
数据来源:狗熊会

2.变量分析探索

#读取数据
import os
os.chdir(r'C:\Users\Administrator\Desktop\狗熊会数据\5.1 北京高档酒店价格分析')
df =pd.read_csv('hoteldata.csv')
#查看数据
df.head()
#查看数据类型
df.info()


数据无缺失值,变量类型正确

#查看描述性统计
df.describe().T
酒店价格

查看酒店价格分布,酒店价格集中在1000-2000元间



未避免残差异方差,因变量需取对数

#酒店房价正太转化
df['房价取对数'] = np.log1p(df['房价']) 
df['房价取对数'].hist(bins=20)
plt.show()
酒店价格取对数

对音箱酒店房价因素的变量进行探索性分布

sns.boxplot(x='房间类型',y='房价取对数',data=df)

方差分析

import statsmodels.api as sm 
from statsmodels.formula.api import ols
ana =ols('房价取对数~C(房间类型)',data=df).fit()
sm.stats.anova_lm(ana)
方差分析

F值显著,房间类型对酒店因素有明显相关性

sns.boxplot(x='地区',y='房价取对数',data=df)

方差分析



F值不显著,地区对酒店因素无明显相关性

sns.scatterplot(x='经度',y='纬度',hue='房价取对数',data=df)

查看酒店经纬度散点图,酒店都集中在市中心,且价格跟市中心距离无太大关联,某些酒店远离市中心但是房价较高,可能为度假区,查看这些数据



百度了一下这个酒店,哇~~


3.修改变量

#变量转换
对时间序列变量,转化为连续变量,将分类变量哑编码
#时间序列变量处理
df['装修年限'] = 2018-df['装修时间']
#对分类变化进行哑变量转换
area = pd.get_dummies(df['地区'])
#以其他城区作为基准组
area.drop('其他城区',axis=1,inplace=True)
housetype  =  pd.get_dummies(df['房间类型'])
#以标准间作为基准组
housetype.drop('标准间',axis=1,inplace=True)
df_model = pd.concat([df,area],axis=1)
df_model = pd.concat([df_model,housetype],axis=1)

相关性分析

#定义自变量和因变量
#自变量
cols = ['卫生评分','服务评分','设施评分','位置评分','评价数','公司','出行住宿','校园生活','装修年限','东城区','朝阳区','海淀区','商务间'
       ,'豪华套间']
#相关性分析
plt.figure(figsize=(12,9))
sns.heatmap(df_model[cols].corr(),vmax=1,annot=True)

相关性高于0.6就具有高共线性,需对变量进行剔除,或者变量转化,将评分属性降维处理,降维为变量'综合评分'

from sklearn.preprocessing import MinMaxScaler
scaler =MinMaxScaler()
#先将评分属性进行标准化处理
df_model[['卫生评分','服务评分','设施评分','位置评分']] = scaler.fit_transform(df_model[['卫生评分','服务评分','设施评分','位置评分']])
from sklearn.decomposition import PCA
pca = PCA()
pca.fit(df_model[['卫生评分','服务评分','设施评分','位置评分']])
pca.explained_variance_ratio_
#其中一个变量就能解释其中90%的变异数据
pca = PCA(n_components=1)
df_model['综合评分'] = pca.fit_transform(df_model[['卫生评分','服务评分','设施评分','位置评分']])
pca.components_
#将公司和出行住宿具有高共线性,将公司变量剔除
cols = ['综合评分','评价数','出行住宿','校园生活','装修年限','东城区','朝阳区','海淀区','商务间'
       ,'豪华套间']

4.构建模型

不进行变量筛选,构建模型

import statsmodels.api as sm
from statsmodels.formula.api import ols
formula = '%s~%s'%('房价取对数','+'.join(cols))
lm_s = ols(formula,data=df_model).fit()
lm_s.summary()

R方0.58,DW:1.117 (DW接近2,残差自相关不存在),模型表现尚可,其中评价数和装修年限相关性不显著(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为标准对变量进行筛选
#定义向前选择法
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,'房价取对数')

筛选后变量为
['综合评分', '豪华套间', '商务间', '出行住宿', '校园生活', '海淀区', '东城区', '朝阳区']
构建模型

formula = '%s~%s'%('房价取对数','+'.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
模型诊断
残差不存在异方差性,模型内变量VIF 小于10,无多重共线性,COOK距离表现正常,无异常点

©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容