当前位置: 首页 > 后端技术 > Python

数据分析——房价分析

时间:2023-03-26 02:01:17 Python

下面我们利用kaggle的Ames房价数据来分析影响房价的相关因素。数据下载:https://www.kaggle.com/c/house-prices-advanced-regression-techniques/data我们要做的是:理解问题。应研究和分析每个变量的意义和重要性。单变量研究。我们只关注因变量SalePrice。多变量研究。我们将尝试了解因变量和自变量之间的关系。数据处理。处理缺失值、离群值和分类变量。检验你的假设。测试数据是否满足研究多变量所需的假设。现在,让我们玩得开心!importpandasaspdimportmatplotlib.pyplotaspltimportseabornassnsimportnumpyasnpfromscipy.statsimportnormfromsklearn.preprocessingimportStandardScalerfromscipyimportstats#testnormaldistributionimportwarningswarnings.filterwarnings'mats('内联#SciPy函数库增加了很多库函数在NumPy库的基础上常用于数学、科学和工程计算。#例如线性代数、常微分方程的数值解、信号处理、图像处理、稀疏矩阵等。file_path="./data/train.csv"df_train=pd.read_csv(file_path)#花点时间理解这些变量的意义及其与本题的相关性#SalePrice(美元)的整体统计说明df_train['SalePrice'].describe()#histogramsns.distplot(df_train['SalePrice'])偏离正态分布,有明显的正偏度,有尖峰#显示偏度skewnessandkurtosiskurtosisprint("Skewness:%f"%df_train['SalePrice'].skew())print("Kurtosis:%f"%df_train['SalePrice'].kurt())#先研究非常相似的变量GrLivArea(地上居住面积)和TotalBsmtSF(地下室总面积)#散点图grlivarea/salepricevar='GrLivArea'data=pd.concat([df_train['SalePrice'],df_train[var]],axis=1)data.plot.scatter(x=var,y='SalePrice',ylim=(0,800000))好像房价saleprice和grlivarea是线性关系#scatterplottotalbsmtsf/saleprice#pd.concat数据拼接,axis=1表示垂直拼接(数量列增加)var='TotalBsmtSF'data=pd.concat([df_train['SalePrice'],df_train[var]],axis=1)data.plot.scatter(x=var,y='SalePrice',ylim=(0,800000))好像是指数关系?并且0个case和分类特征之间有一些关系#boxplotboxplotoverallqual/saleprice整体材料和加工质量,1-10级#df_train['OverallQual'].describe()var='OverallQual'data=pd.concat([df_train['SalePrice'],df_train[var]],axis=1)#f,ax=plt.subplots(figsize=(8,6))plt.figure(figsize=(8,6))fig=sns.boxplot(x=var,y='SalePrice',data=data)fig.axis(ymin=0,ymax=800000)#原始建造日期YearBuilt与SalePrice的关系var='YearBuilt'data=pd.concat([df_train['SalePrice'],df_train[var]],axis=1)plt.图(figsize=(20,8))fig=sns.boxplot(x=var,y="SalePrice",data=data)fig.axis(ymin=0,ymax=800000)plt.xticks(rotation=45)#x轴标签的斜率不是一个明显的趋势,但我认为新房子应该比旧的销售价格高总结1.GrLivArea和TotalBsmtSF似乎与SalePrice线性相关。两种关系都是正向的,这意味着当一个变量增加时,另一个变量也会增加。TotalBsmtSF和SalePrice之间的关系具有特别高的斜率2。OverallQual和YearBuilt似乎也与SalePrice相关。在OverallQual中,关系更强。上面分析的四个变量主观上认为与saleprice相关,我们需要更客观地分析1.关系矩阵(热图)2.与saleprice的关系矩阵3.最相关变量之间的散点图#correlationmatrix#计算每列之间的相关性corrmat=df_train.corr()#print(corrmat)#plt.figure(figsize=(12,9))f,ax=plt.subplots(figsize=(12,9))sns.heatmap(corrmat,vmax=.8,square=True)totalbsmtsf和1stflrsf形成的白色方块与garageX(3)形成的白色方块显示出很强的相关性,热图对展示多重共线性很有用。还可以看出,GrLivArea、TotalBsmtSF和OverallQual与salePrice具有明显的相关性,但也可以看出还应考虑其他一些变量。#SalePricecorrelationmatrixk=10#热图有10个变量,为什么选择10个?cols=corrmat.nlargest(k,'SalePrice')['SalePrice'].index#与saleprice相关性最高的10行索引cm=np.corrcoef(df_train[cols].values.T)#.什么是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确实与salepricegaragecars高度相关,garagearea只保留一个用于分析。因为车库的面积直接决定了可以容纳的车辆数量,所以保留garagecars因为它比较有针对性。#sns.pairplot函数绘制两个变量之间的关系,kind="reg"可以为散点图拟合一条直线,hue="某个字段"可以按照某个字段进行分类,platte控制颜色分类sns.set()cols=['SalePrice','OverallQual','GrLivArea','GarageCars','TotalBsmtSF','FullBath','YearBuilt']sns.pairplot(df_train[cols],kind="reg",size=2.5)plt.show()可以发现很多有趣的关系,比如地下室总面积totalbsmtsf和grlivarea的居住面积形成一条分界线,点基本分布在下面,因为地下室的面积一般不超过居住面积。处理缺失值,思考缺失值:缺失很常见吗?是随机的还是缺失的?#missingdatatotal=df_train.isnull().sum().sort_values(ascending=False)percent=(df_train.isnull().sum()/df_train.isnull().count()).sort_values(ascending=False)#print(total)#print(percent)missing_data=pd.concat([total,percent],axis=1,keys=['Total','Percent'])missing_data.head(20)#有20个字段包含空值#游泳池的质量,其他类别特征,道路的类型,围栏的质量等等,我们可以删掉,因为买房的时候不考虑这些因素。#garageX也可以删掉,因为我们分析了garagecars最重要的因素,bsmtX也是(已经有totalbsmtSF)#MasVnrX,我们可以认为不重要,他们和yearbuilt和overallqual有很强的相关性,还有这些两个我们已经考虑到了,所以删除MasVnrX不会丢失信息#最后一个是electrical,只有一个缺失值,我们将缺失值删除,保留这个变量#dealingwithmissingdatadf_train=df_train.drop((missing_data[missing_data['Total']>1].index,1)#df_trainremaining18columns#删除electrical空值所在行df_train=df_train.drop(df_train.loc[df_train['Electrical'].isnull()].index)#checkdf_train.isnull().sum().max()outliersoutliers!异常值通常是很重要的一个部分,它可能会影响我们的模型,也会给我们带来一些具体行为的信息,值得关注!我们用标准差和散点图来分析yzesaleprice#首先,我们必须确定一个阈值来定义异常值。#将数据标准化,即均值为0,方差为1#newaxis增加维度,索引多维数组saleprice_scaled=StandardScaler().fit_transform(df_train['SalePrice'][:,np.newaxis])#argsort()返回升序排序后,每个元素的原始序号(从0开始)#saleprice_scaled共1459,返回前10和后10low_range=saleprice_scaled[saleprice_scaled.flatten().argsort()][:10]high_range=saleprice_scaled[saleprice_scaled.flatten().argsort()][-10:]print('分布的外部范围(低):')print(low_range)print('\n分布的外部范围(高):')print(high_range)lowrange比较相似,离0不远。highrange在0到7之间。有些值超出了范围。注意两个值都在7以上。双变量分析#saleprice/grlivareavar='GrLivArea'data=pd.concat([df_train['SalePrice'],df_train[var]],axis=1)data.plot.scatter(x=var,y='SalePrice',ylim=(0,800000))可以观察到有两个特殊的值,面积大但是房价比较低,可能是农区或者之类的,不能代表整体趋势,可以定义为离群值,剔除。#deletingdf_train.sort_values(by='GrLivArea',ascending=False)[:2]#索引:1299,523df_train=df_train.drop(df_train[df_train['Id']==1299].index)df_train=df_train.drop(df_train[df_train['Id']==524].index)#saleprice/totalbsmtsf(地下室总面积)var='TotalBsmtSF'data=pd.concat([df_train[var],df_train['SalePrice']],axis=1)data.plot.scatter(x=var,y='SalePrice',ylim=(0,800000))一些离散点在可以接受的范围内,不需要删除需要的四个假设被测试。正态性-测试销售价格是否服从正态分布同方差性-同方差性意味着假设因变量在预测变量的范围内具有相同的方差水平???线性-一种常用的方法是绘制散点图以找到线性模式。如果不是线性的,研究数据转换。没有相关错误——当一个错误与另一个错误相关时,就会出现相关错误。通常发生在时间序列中,如果检测到某些东西,则尝试添加一个变量来解释产生的效果,这是相关错误最常见的解决方案。#normality#Histogram:testkurtosisandskewness#Normaldistributionprobabilitymap:数据的分布要尽可能符合正态分布数据概率分布的方法(默认测试正态分布),红色表示正态分布,蓝色为样本数据,蓝色越接近红色越符合预期分布fig=plt.figure()res=stats.probplot(df_train['SalePrice'],plot=plt)saleprice不是正态分布,是正偏态(右偏态)的情况,可以通过对数进行变换。#logtransformationdf_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)#grlivareasns.distplot(df_train['GrLivArea'],fit=norm)fig=plt.figure()res=stats.probplot(df_train['GrLivArea'],plot=plt)#日志transformdf_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)#totalbsmtsfsns.distplot(df_train['TotalBsmtSF'],fit=norm)fig=plt.figure()res=stats.probplot(df_train['TotalBsmtSF'],plot=plt)#now有一个问题。发现数据中有很多0。这是对数变换做不到的。它对所有非零值使用对数变换,不处理0值。这也保留了0表示没有地下室的特点。#创建一个新变量,如果area>1它得到1,对于area==0它得到0df_train['HasBsmt']=pd.Series(len(df_train['TotalBsmtSF']),index=df_train.index)df_train['HasBsmt']=0df_train.loc[df_train['TotalBsmtSF']>0,'HasBsmt']=1df_train.loc[df_train['HasBsmt']==1,'TotalBsmtSF']=np.log(df_train['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)#Verifyhomoscedasticity#GrLivAreaplt.scatter(df_train['GrLivArea'],df_train['SalePrice'])可以看到即经过法线变换后,不再呈现散点图圆锥形为#TotalBsmtSFplt.scatter(df_train[df_train['TotalBsmtSF']>0]['TotalBsmtSF'],df_train[df_train['TotalBsmtSF']>0]['SalePrice'])我们可以说,在一般情况下,saleprice在totalbsmtsf范围内表现出相同水平的差异#Convertcategoricalvariablestodummyvariables(dummy)df_train=上面的pd.get_dummies(df_train)summary分析了销售价格和一些最相关的变量,处理了数据的缺失值和异常值,测试了一些基本的统计假设,最后将分类变量转化为虚拟变量。Python帮了大忙!