之前我们爬取了贝壳找房上的北京二手房信息,具体可以查看python爬取贝壳找房之北京二手房源信息,现在我们针对获取的数据进行分析及可视化的展示,本文代码和数据均存放在github上,链接地址:贝壳找房数据分析源码及数据,更多内容可查看个人博客:大圣的专属空间
数据预处理
由于我们爬取的数据有的会存在缺失及错乱,先对原始数据(beike_find_house - 副本.xlsx)进行清洗及格式化的处理,具体代码如下:
首先进行加载数据并且对其进行列名重命名:
import pandas as pdimport numpy as npfrom matplotlib import pyplot as pltimport csvdata = pd.read_excel(r"F:\0_个人学习\3_数据分析与挖掘\2_案例实战\AI之房产信息分析\beike_find_house.xlsx", header=None)data.columns = ['区/县','区域','小区','总价','单价','房屋户型','楼层','总面积','户型结构','套内面积','建筑类型','朝向','建筑结构','装修情况','梯户比例','供暖方式','配备电梯','产权年限','s','交易权属','u','形式','是否满五','产权形式','是否有房本','小区均价','小区建成','style','总栋数']
使用data.head()查看前五行数据,如下:
现在对数据进行清洗,因为在爬取的原始数据中有的缺失所以导致数据错乱,对其清洗比较繁琐,代码如下:
# 数据清洗data['装修情况'] = data.apply(lambda x:x['建筑类型'] if ('南北' in str(x['户型结构'])) else x['装修情况'],axis=1)data['建筑结构'] = data.apply(lambda x:x['套内面积'] if ('南北' in str(x['户型结构'])) else x['建筑结构'],axis=1)data['朝向'] = data.apply(lambda x:x['户型结构'] if ('南北' in str(x['户型结构'])) else x['朝向'],axis=1)data['套内面积'] = data.apply(lambda x:'㎡' if ('南北' in str(x['户型结构'])) else x['套内面积'],axis=1)data['装修情况'] = data.apply(lambda x:x['朝向'] if ('㎡' in str(x['户型结构'])) else x['装修情况'],axis=1)data['建筑结构'] = data.apply(lambda x:x['建筑类型'] if ('㎡' in str(x['户型结构'])) else x['建筑结构'],axis=1)data['朝向'] = data.apply(lambda x:x['套内面积'] if ('㎡' in str(x['户型结构'])) else x['朝向'],axis=1)data['套内面积'] = data.apply(lambda x:'㎡' if ('㎡' in str(x['户型结构'])) else x['套内面积'],axis=1)data['套内面积'] = data.apply(lambda x:'㎡' if ('暂无数据' in str(x['套内面积'])) else x['套内面积'],axis=1)data['装修情况'] = data.apply(lambda x:x['装修情况'] if ('㎡' in str(x['套内面积'])) else x['建筑结构'],axis=1)data['建筑结构'] = data.apply(lambda x:x['建筑结构'] if ('㎡' in str(x['套内面积'])) else x['朝向'],axis=1)data['朝向'] = data.apply(lambda x:x['朝向'] if ('㎡' in str(x['套内面积'])) else x['建筑类型'],axis=1)data['建筑类型'] = data.apply(lambda x:x['建筑类型'] if ('㎡' in str(x['套内面积'])) else x['套内面积'],axis=1)data['套内面积'] = data.apply(lambda x:x['套内面积'] if ('㎡' in str(x['套内面积'])) else '无信息',axis=1)data['装修情况'] = data.apply(lambda x:x['建筑结构'] if (('户') in str(x['装修情况'])) else x['装修情况'],axis=1)data['建筑结构'] = data.apply(lambda x:x['朝向'] if (('户') in str(x['装修情况'])) else x['建筑结构'],axis=1)data['朝向'] = data.apply(lambda x:x['建筑类型'] if (('户') in str(x['装修情况'])) else x['朝向'],axis=1)data['建筑结构'] = data.apply(lambda x:x['朝向'] if ('结构' in str(x['朝向'])) else x['建筑结构'],axis=1)data['朝向'] = data.apply(lambda x:x['建筑类型'] if ('结构' in str(x['朝向'])) else x['朝向'],axis=1)data['总楼层'] = data.apply(lambda x:str(x[6])[3:].strip('(共').strip('层)'),axis=1)data['楼层'] = data.apply(lambda x:str(x[6])[:3],axis=1)data['总面积'] = data.apply(lambda x:str(x[7]).strip('㎡'),axis=1)data['小区均价'] = data.apply(lambda x:str(x[-5]).strip('元/㎡\n').strip('\n'),axis=1)data['小区建成'] = data.apply(lambda x:str(x[-4])[:4],axis=1)data['总栋数'] = data.apply(lambda x:str(x[-2])[:-1],axis=1)
通过上述代码,我们对原始清洗完成,并且我们通过下面的代码将其保存在新的csv文件里,处理后的文件请查看:北京二手房处理后的数据
data.to_csv('after_deal_data.csv',encoding='utf_8_sig')
注:上述代码中to_csv保存文件出现中文乱码时候添加encoding='utf_8_sig'
数据分析
上述的原始数据比较多,本次仅取需要的字段进行分析,如下:
need_data = data[['区/县','区域','小区','总价','单价','房屋户型','楼层','总面积','朝向','建筑结构','装修情况','交易权属','形式','是否满五','产权形式','是否有房本','小区均价','小区建成','总栋数']] need_data.head()
结果如下:
按照一贯步骤,使用need_data.info()和need_data.describe()来显示统计信息,结果就不公布了,自己运行即可
先对北京整个区、县的房源数量信息进行分析
# 图表中文显示plt.rcParams['font.sans-serif'] = ['SimHei'] # 步骤一(替换sans-serif字体)plt.rcParams['axes.unicode_minus'] = False # 步骤二(解决坐标轴负数的负号显示问题)fig, ax=plt.subplots()'''各区县房源分布情况!!!'''need_data['区/县'].value_counts().plot(kind='bar',color=['green','red','blue','grey','pink'],alpha=0.5)plt.title('北京二手房各区、县房源分布信息!',fontsize=15)plt.xlabel('区、县名称',fontsize=15)plt.ylabel('房源数量',fontsize=15)plt.grid(linestyle=":", color="r")plt.xticks(rotation=60)plt.legend()plt.show()
结果如下:
可以看出朝阳、丰台的二手房源数量最多,平谷、亦庄、门头沟房源较少,说明接近市中心的房源数量较多,离市中心较远的房源数量较少
对各区房源均价进行分析,代码如下:
'''各区县房源均价分布情况!!!'''need_data.groupby('区/县').mean()['单价'].sort_values(ascending=True).plot(kind='barh',color=['r','g','y','b'],alpha=0.5)plt.title('北京二手房各区、县房屋均价分布信息!',fontsize=15)plt.xlabel('房屋均价',fontsize=15)plt.ylabel('区、县名称',fontsize=15)plt.grid(linestyle=":", color="r")plt.legend()plt.show()
结果如下:
可以看出西城、东城、海淀的房屋均价较高,房山、平谷、门头沟房源单价较低,东西城为市中心,海淀为教育资源丰富,学区房较多,所以价格较高,平谷、房山等离市区较远,价格相对较低,符合实际情况
接下来分析房屋户型情况,代码类似于上面,本文直接给出结果,需要源码的可以查看github上的资源,后续没给出代码的类似,结果如下:
由于房屋户型种类较多,本次只显示了数量靠前的十种房屋户型,可以看出两居室的数量最多,符合大多数家庭的基本需求,同时我们在分析的过程中发现了好多房屋户型就一套房的信息,因此也查看了此类房的基本信息,本次仅查看了5室2厅4卫房型的房屋基本信息,其他的可以参考该代码:
need_data[need_data.房屋户型 == '5室2厅4卫']
结果如下:
可以看出该房源位于东城天坛地区于1978年建成,属于私产,单价5.5万左右,对比周边均价,其价格不算太高
同时我们也提取了总价最低和最高的房源信息,代码如下:
# 北京二手房总价最大、最小值及其房源信息total_price_min = need_data['总价'].min()total_price_min_room_info = need_data[need_data.总价==total_price_min]print('二手房总价最低价位为:\n{}'.format(total_price_min))print('二手房总价最低的房源信息为:\n{}'.format(total_price_min_room_info))total_price_max = need_data['总价'].max()total_price_max_room_info = need_data[need_data.总价==total_price_max]print('二手房总价最高价位为:\n{}'.format(total_price_max))print('二手房总价最低的房源信息为:\n{}'.format(total_price_max_room_info))
结果如下:
接下来我们分析房屋总价和总面积的关系图,使用散点图进行展示,代码如下:
# 绘制总面积和总价的散点关系图home_area = need_data['总面积'].apply(lambda x:float(x))# print(home_area.head())total_price = need_data['总价']# print(total_price.head())plt.scatter(home_area,total_price,s=3)plt.title('北京二手房房屋户型情况',fontsize=15)plt.xlabel('房屋面积',fontsize=15)plt.ylabel('房源总价',fontsize=15)plt.grid(linestyle=":", color="r")plt.show()
结果如下:
可以看出房屋价格随着房屋面积的增长而增长,同时我们也提取了房屋面积最大,但是价格较低的房源信息,如下:
# 分析面积大但是价格较低的房源area_max = home_area.max()area_max_room_info = need_data[home_area==area_max]print('二手房面积最大的房源信息为:\n{}'.format(area_max_room_info))
结果如下:
可以看出该房源位于天通苑,总面积较大,单价相对小区均价较低
接下来看看房源装修情况的分布,代码类似,直接给出结果,如下:
可以看出,装修好的房源数量最多,因为大多数二手房源都是用户自己住过的,少数的毛坯房可能是炒房的、家里有矿的或者拆迁户囤的房产,符合实际情况,价格的话精装价格也是相对较高,但是总体价格和装修类型的关系差别不太大
同样的,我们也提取了小区均价最高及最低的房源信息,结果如下:
可以看到最低价格位于离市区较远的房山区、价格最高的位于繁华的金融街附近,看到此价格让我们普通人望而却步!
接下来我们给出小区建成时间和小区均价的关系图,代码如下:
# 剔除小区建成时间为暂无数据的两条数据try:need_data = need_data.drop([1931,2527])except:print('数据已经剔除!!!')need_data[need_data.小区建成=='暂无数据']# 将小区建成时间转成日期并仅提取其中的年份built_year = pd.to_datetime(need_data.小区建成).dt.year# 绘制小区建成年限与小区均价的散点分布图plt.scatter(built_year,need_data['小区均价'].astype(float),s=6)plt.title('北京二手房小区建成年份与均价分布信息!',fontsize=15)plt.xlabel('小区建成年份',fontsize=15)plt.ylabel('房屋均价',fontsize=15)plt.grid(linestyle=":", color="r")plt.xticks(rotation=0)plt.show()
注:在分析中发现小区建成时间有两个字段暂时没有数据,我们本次采用直接剔除的方式,最终散点关系图如下:
可以看出基本小区建成时间越晚,价格越高,当然对于那些建造时间较早但是价格较高的都是因为其位于市中心或者属于比较好的学区房
接下来我们给出楼层和价格的关系,代码可以查看github,最终结果如下:
中层和低层价格稍微高点,但是整体差别不是很大,毕竟这是在北京,其他地区的话可能会优点差距
最后我们简单了使用了下pyecharts绘制了楼层和房源数量的饼图,代码如下:
# 使用pyecharts绘制楼层和房屋数量的饼图import pyecharts as pyex = avg_price_louceng.indexy = avg_price_louceng.valuespie = pye.Pie("房源分布信息")pie.add("",x,y,is_label_show=True)pie.render()
转存失败重新上传取消
最终结果如下:
根据结果看出来,按楼层分类的房源数量基本差别不大
总结
本文对之前爬取的北京二手房数据进行了简单的数据分析以及一些可视化展示,熟悉了数据分析的一些工具包的使用,同时也简单的了解了echart的使用,后面会根据数据的一些特征运用机器学习算法对二手房价格进行预测分析,后续还需要加深数据分析工具的使用。