python链家二手房分析
python数据分析项目:链家二手房分析
数据来源:爬虫获取
数据内容:北京二手房数据
数据特征:11个特征变量 , 1个目标变量 Price
Direction : 房屋位置所处的方向
District : 房屋位置
Elevator : 电梯
Floor : 楼层
Garden : 小区名字
Id : 房屋编号
Layout:户型
Price : 价格
Region : 区域
Renovation : 装修程度
Size : 房屋面积
Year : 房屋年份
1、数据准备
#导入数据包 import numpy as np import pandas as pd #导入画图包 import matplotlib.pyplot as plt import missingno as msno import seaborn as sns sns.set() sns.set_style({\'font.sans-serif\':[\'simhei\',\'Arial\']}) #jupyter notebook绘图设置 %matplotlib inline %config InlineBack.figure_format="retina" #读取数据 lianjia_df = pd.read_csv("E:/数据分析/数据分析项目实战/python分析链家二手房数据/lianjia.csv") lianjia_df.head(5)
初步观察,Elvator字段中存在缺失值。
下一步检查缺失情况,有两种方式。
# 检查缺失值情况 lianjia_df.info()
#可视化查询缺失值 msno.matrix(lianjia_df,figsize=(12,5))
由此可见,Elvator字段中缺失大量的值。
lianjia_df.describe()
上面结果给出了特征值是数值的一些统计值,包括平均数,标准差,中位数,最小值,最大值,25%分位数,75%分位数。这些统计结果简单直接,对于初始了解一个特征好坏非常有用,比如我们观察到 Size 特征 的最大值为1019平米,最小值为2平米,那么我们就要思考这个在实际中是不是存在的,如果不存在没有意义,那么这个数据就是一个异常值,会严重影响模型的性能。
# 添加新字段 # 房屋均价 df = lianjia_df.copy() df["PerPrice"] = lianjia_df["Price"]/lianjia_df["Size"]
#重新摆放列位置 columns = [\'Region\', \'District\', \'Garden\', \'Layout\', \'Floor\', \'Year\', \'Size\', \'Elevator\', \'Direction\', \'Renovation\', \'PerPrice\', \'Price\'] df = pd.DataFrame(df,columns = columns) df.head()
这里添加了新的特征 “PerPrice”,特征的顺序也进行了调整,Id没什么分析意义,将其移除。
2、数据分析
# Region特征分析
对于区域特征,可以分析不同区域房价(总价和单价)和 数量的对比。
# 对二手房区域分组对比二手房数量和每平米房价 df_house_count = df.groupby(\'Region\')[\'Price\'].count().sort_values(ascending=False).to_frame().reset_index() df_house_mean = df.groupby(\'Region\')[\'PerPrice\'].mean().sort_values(ascending=False).to_frame().reset_index() f, [ax1,ax2,ax3] = plt.subplots(3,1,figsize=(20,15)) sns.barplot(x=\'Region\', y=\'PerPrice\', palette="Blues_d", data=df_house_mean, ax=ax1) ax1.set_title(\'北京各大区二手房每平米单价对比\',fontsize=15) ax1.set_xlabel(\'区域\') ax1.set_ylabel(\'每平米单价\') sns.barplot(x=\'Region\', y=\'Price\', palette="Greens_d", data=df_house_count, ax=ax2) ax2.set_title(\'北京各大区二手房数量对比\',fontsize=15) ax2.set_xlabel(\'区域\') ax2.set_ylabel(\'数量\') sns.boxplot(x=\'Region\', y=\'Price\', data=df, ax=ax3) ax3.set_title(\'北京各大区二手房房屋总价\',fontsize=15) ax3.set_xlabel(\'区域\') ax3.set_ylabel(\'房屋总价\') plt.show()
可以看出:
- 二手房均价:西城区的房价最贵均价大约11万/平,因为西城在二环以里,且是热门学区房的聚集地。其次是东城大约10万/平,然后是海淀大约8.5万/平,其它均低于8万/平。
- 二手房房数量:从数量统计上来看,目前二手房市场上比较火热的区域。海淀区和朝阳区二手房数量最多,差不多都接近3000套,毕竟大区,需求量也大。然后是丰台区,近几年正在改造建设,有赶超之势。
- 二手房总价:通过箱型图看到,各大区域房屋总价中位数都都在1000万以下,且房屋总价离散值较高,西城最高达到了6000万,说明房屋价格特征不是理想的正太分布。
# Size特征分析
f, [ax1,ax2] = plt.subplots(1, 2, figsize=(15, 5)) # 建房面积的分布情况 sns.distplot(df[\'Size\'], bins=20, ax=ax1, color=\'r\') sns.kdeplot(df[\'Size\'], shade=True, ax=ax1) # 建房面积和出售价格的关系 sns.regplot(x=\'Size\', y=\'Price\', data=df, ax=ax2) plt.show()
Size 分布:通过 distplot 和 kdeplot 绘制柱状图观察 Size 特征的分布情况,属于长尾类型的分布,这说明了有很多面积很大且超出正常范围的二手房。
Size 与 Price 的关系:
通过 regplot 绘制了 Size 和 Price 之间的散点图,发现 Size 特征基本与Price呈现线性关系,符合基本常识,面积越大,价格越高。
但是有两组明显的异常点:1. 面积不到10平米,但是价格超出10000万;2. 一个点面积超过了1000平米,价格很低,需要查看是什么情况。
df.loc[df["Size"]<10]
经过查看发现这组数据是别墅,出现异常的原因是由于别墅结构比较特殊(无朝向无电梯),
字段定义与二手商品房不太一样导致爬虫爬取数据错位。
也因别墅类型二手房不在我们的考虑范围之内,故将其移除再次观察Size分布和Price关系。
df.loc[df[\'Size\']>1000]
经观察这个异常点不是普通的民用二手房,很可能是商用房,所以才有1房间0厅确有如此大超过1000平米的面积,这里选择移除。
df = df[(df[\'Layout\']!=\'叠拼别墅\')&(df[\'Size\']<1000)] f,[ax1,ax2] = plt.subplots(1,2,figsize=(15,5)) # 建房面积的分布情况 sns.distplot(df[\'Size\'], bins=20, ax=ax1, color=\'r\') sns.kdeplot(df[\'Size\'], shade=True, ax=ax1) # 建房面积和出售价格的关系 sns.regplot(x=\'Size\', y=\'Price\', data=df, ax=ax2) plt.show()
、
重新进行可视化发现就没有明显的异常点了。
#Layout特征分析
f, ax1= plt.subplots(figsize=(20,20)) sns.countplot(y=\'Layout\', data=df, ax=ax1) ax1.set_title(\'房屋户型\',fontsize=15) ax1.set_xlabel(\'数量\') ax1.set_ylabel(\'户型\') plt.show()
这个特征真是不看不知道,各种厅室组合搭配,竟然还有9室3厅,4室0厅等奇怪的结构。
其中,2室一厅占绝大部分,其次是3室一厅,2室2厅,3室两厅。
但是仔细观察特征分类下有很多不规则的命名,比如2室一厅与2房间1卫,还有别墅,没有统一的叫法。
这样的特征肯定是不能作为机器学习模型的数据输入的,需要使用特征工程进行相应的处理。
#Renovation 特征分析
df[\'Renovation\'] = df.loc[(df[\'Renovation\'] != \'南北\'), \'Renovation\'] 精装 11345 简装 8497 其他 3239 毛坯 576 南北 20 Name: Renovation, dtype: int64
发现Renovation装修特征中竟然有南北,它属于朝向的类型,可能是因为爬虫过程中一些信息位置为空,导致“Direction”朝向特征出现在这里,所以需要清除或替换掉。
# 去掉错误数据“南北”,因为爬虫过程中一些信息位置为空,导致“Direction”的特征出现在这里,需要清除或替换 df[\'Renovation\'] = df.loc[(df[\'Renovation\'] != \'南北\'), \'Renovation\'] # 画幅设置 f, [ax1,ax2,ax3] = plt.subplots(1, 3, figsize=(20, 5)) sns.countplot(df[\'Renovation\'], ax=ax1) sns.barplot(x=\'Renovation\', y=\'Price\', data=df, ax=ax2) sns.boxplot(x=\'Renovation\', y=\'Price\', data=df, ax=ax3) plt.show()
观察到,精装修的二手房数量最多,简装其次,也是我们平日常见的。而对于价格来说,毛坯类型却是最高,其次是精装修。
#Elevator 特征分析
初探数据的时候,我们发现 Elevator 特征是有大量缺失值的,这对于我们是十分不利的,首先我们先看看有多少缺失值:
misn = len(df.loc[(df[\'Elevator\'].isnull()), \'Elevator\']) print(\'Elevator缺失值数量为:\'+ str(misn))
Elevator 缺失值数量为:8237
这么多的缺失值怎么办呢?这个需要根据实际情况考虑,常用的方法有平均值/中位数填补法,直接移除,或者根据其他特征建模预测等。
这里我们考虑填补法,但是有无电梯不是数值,不存在平均值和中位数,怎么填补呢?这里给大家提供一种思路:就是根据楼层 Floor 来判断有无电梯,一般的楼层大于6的都有电梯,而小于等于6层的一般都没有电梯。有了这个标准,那么剩下的就简单了。
# 由于存在个别类型错误,如简装和精装,特征值错位,故需要移除 df[\'Elevator\'] = df.loc[(df[\'Elevator\'] == \'有电梯\')|(df[\'Elevator\'] == \'无电梯\'), \'Elevator\'] # 填补Elevator缺失值 df.loc[(df[\'Floor\']>6)&(df[\'Elevator\'].isnull()), \'Elevator\'] = \'有电梯\' df.loc[(df[\'Floor\']<=6)&(df[\'Elevator\'].isnull()), \'Elevator\'] = \'无电梯\' f, [ax1,ax2] = plt.subplots(1, 2, figsize=(20, 10)) sns.countplot(df[\'Elevator\'], ax=ax1) ax1.set_title(\'有无电梯数量对比\',fontsize=15) ax1.set_xlabel(\'是否有电梯\') ax1.set_ylabel(\'数量\') sns.barplot(x=\'Elevator\', y=\'Price\', data=df, ax=ax2) ax2.set_title(\'有无电梯房价对比\',fontsize=15) ax2.set_xlabel(\'是否有电梯\') ax2.set_ylabel(\'总价\') plt.show()
结果观察到,有电梯的二手房数量居多一些,毕竟高层土地利用率比较高,适合北京庞大的人群需要,而高层就需要电梯。相应的,有电梯二手房房价较高,因为电梯前期装修费和后期维护费包含内了(但这个价格比较只是一个平均的概念,比如无电梯的6层豪华小区当然价格更高了)。
#Year 特征分析
grid = sns.FacetGrid(df, row=\'Elevator\', col=\'Renovation\', palette=\'seismic\',size=4) grid.map(plt.scatter, \'Year\', \'Price\') grid.add_legend()
在Renovation和Elevator的分类条件下,使用 FaceGrid 分析 Year 特征,观察结果如下:
- 整个二手房房价趋势是随着时间增长而增长的;
- 2000年以后建造的二手房房价相较于2000年以前有很明显的价格上涨;
- 1980年之前几乎不存在有电梯二手房数据,说明1980年之前还没有大面积安装电梯;
- 1980年之前无电梯二手房中,简装二手房占绝大多数,精装反而很少;
#Floor 特征分析
f, ax1= plt.subplots(figsize=(20,5)) sns.countplot(x=\'Floor\', data=df, ax=ax1) ax1.set_title(\'房屋户型\',fontsize=15) ax1.set_xlabel(\'数量\') ax1.set_ylabel(\'户型\') plt.show()
可以看到,6层二手房数量最多,但是单独的楼层特征没有什么意义,因为每个小区住房的总楼层数都不一样,我们需要知道楼层的相对意义。
另外,楼层与文化也有很重要联系,比如中国文化七上八下,七层可能受欢迎,房价也贵,而一般也不会有4层或18层。
当然,正常情况下中间楼层是比较受欢迎的,价格也高,底层和顶层受欢迎度较低,价格也相对较低。
所以楼层是一个非常复杂的特征,对房价影响也比较大。