2020链家杭州二手房数据分析(截止到2020年09月07日)
2020链家杭州二手房数据分析(截止到2020年09月07日)
1 项目背景
通过python爬去链家杭州二手房的数据,网址为:https://hz.lianjia.com/ershoufang/。可以发现,链家把杭州分为15个区域。其中,截止到2020年09月07日,桐庐和建德区域数据为0条,大江东数据为2两条,淳安数据共32条。和其他区域相比,这几个区域数据量太小,因此在后续爬去过去中略去。
通过requests
和BeautifulSoup
库爬取和解析,代码就不放了,很简陋。注意每次爬取后设置随机间隔时间,做个简单的反反爬虫,不然会被封IP。我设置的间隔时间为random.randint(0,2) + random.random()
。最终,一共获得了31, 230条记录。
2 理解数据
数据含义如下:
字段名 | 字段含义 |
---|---|
postion | 具体位置 |
Layout | 房屋布局 |
Size | 房屋面积 |
Directioin | 房屋朝向 |
Renovation | 装修情况 |
Floor | 楼层 |
Structure | 房屋结构(板楼、塔楼) |
totalPrice | 总价格 |
unitPrice | 单价 |
District | 所在区县 |
3 探索数据
3.1 数据查看
通过pandas导入数据df = pd.read_excel('lz_hangzhou-copy.xlsx')
后,使用df.head(10)
简单查看前10行数据。结果如下:
3.2 数据清洗
3.2.1 缺失值
再看看有没有缺失值:df.isnull().sum().sort_values()
,没有发现缺失值。数据维护的挺好。
3.2.2 unitPrice列
接下来,处理unitPrice列。需要吧汉字去除和‘/’去掉。观察一下,可以使用正则表达式找出其中的数字。
df['unitPrice'] = df['unitPrice'].apply(lambda x: str(x)).str.findall("(\d+)").str[0].astype("float")
3.2.3 Floor列
然后处理Floor列。在这一列,数据可以分为两部分:a. 楼层位置(高、低、中); b. 层数。两部分可以由’()'分开。我们需要将这两部分新建两列,代替原来的Floor列。
首先,我们看一下不符合这个形式的记录共有多少行。df.shape[0]-df['Floor'].str.contains('\(').sum()
,返回结果是1741
,占总数据的5.6%。那我们将把这些记录删掉,df = df.loc[df['Floor'].str.contains('\(')]
。然后把Floor列拆分成floorType和totalFloor两列,分别表示楼层位置和总层数,再删除原来的Floor列。代码如下:
df['floorType'] = df['Floor'].str.split('(').str[0]
df['totalFloor'] = df['Floor'].str.split('(').str[1].str.\
findall('\d+').str[0].astype('int')
df.drop('Floor', axis=1, inplace=True)
看一下现在的数据:df.head()
3.2.4 Structure列
首先,看看Structure列的数据构成:df['Structure'].unique()
.
array([' 板楼', ' 塔楼', ' 板塔结合', ' 暂无数据'], dtype=object)
我们需要把每个类型名称中的空格去除,然后删掉’暂无数据’的记录。代码如下:
df['Structure'] = df['Structure'].str.strip()
df = df[df['Structure'] != '暂无数据']
3.2.5 Renovation列
同样,该列的数据中也有空格:
array([' 精装 ', ' 简装 ', ' 毛坯 '], dtype=object)
换一种方式去除空格。
def reno(x):if '精装' in x: return '精装'if '简装' in x: return '简装'if '毛坯' in x: return '毛坯'df['Renovation'] = df['Renovation'].apply(reno)
3.2.6 Direction列
这一列的数据构成比较多样:
array([' 南 ', ' 东 南 北 ', ' 南 北 ', ' 南 西 ', ' 东 ', ' 北 南 ', ' 东 南 ',' 东南 ', ' 南 西 北 ', ' 西 ', ' 西南 ', ' 北 ', ' 西 北 ', ' 西北 ',' 南 西南 北 ', ' 东南 南 '], dtype=object)
仔细观看可以发现以下几种情况:
- 单一朝向:’ 东 ', ‘ 南 ’, ‘ 西 ’, ‘ 北 ’, ‘ 西南 ’, ‘ 西北 ’,‘ 东南 ’
- 两种朝向:’ 南 北 ', ’ 南 西 ', ’ 北 南 ', ’ 东 南 ',
- 三种朝向:’ 东 南 北 ‘,’ 西 西南 南 ‘,’ 南 西 北 ',等等。
针对单一朝向的,直接去除空格。而对于多种朝向,为了后续分析方便,则简化为单种朝向,并将最终值赋予Orientation列。
def direct(x):if "东南" in x:if x.count("南") > 1:if ("西南" in x) & ("南" not in x):return "东南"else:return "南"else:return "东南"elif "西南" in x:if x.count("南") >1:return "南"else:return "西南"elif "东北" in x:return "东北"elif "西北" in x:return "西北"elif "东" in x:return "东"elif "西" in x:return "西"elif "南" in x:return "南"elif "北" in x:return "北"df['Orientation'] = df['Direction'].apply(direct)
df.drop('Direction', axis=1, inplace=True)
3.2.6 Size列
观察可以发现,面积都是浮点数,用正则表达式提取即可。
df['Size'] = df['Size'].str.findall('[\d,.]+').str[0].astype('float')
3.2.7 Layout列
这一列的信息为房屋格局,如3室2厅,把室的信息和厅的信息提取出来,分别存储。
df['Room'] = df['Layout'].str.findall('(\d)室(\d)厅').str[0].str[0].astype('int')
df['Hall'] = df['Layout'].str.findall('(\d)室(\d)厅').str[0].str[1].astype('int')
df.drop('Layout', axis=1, inplace=True)
3.2.8 Follow列
关注人数为整数,提取出来。
df['Follow'] = df['Follow'].str.findall('\d+').str[0].astype('int')
3.2.9 异常值处理
先看看有没有异常值:df.describe()
从数据来看,各项值基本正常。
4 数据可视化
4.1 探索变量相关性
看看几个列的相关性。注意,pandas中默认的相关是皮尔逊相关系数,要求数据是连续变量。而我们的数据中,只有Size, totalPrice, unitPrice是连续变量,所以这个图就作为一个参考吧。这几列数据的相关性挺高。
corr = df.corr()
plt.figure(figsize=(8,6))
sns.heatmap(corr, cmap='GnBu')
plt.show()
4.2 杭州市各区域房源平均总价对比
total_district = df.groupby('District')['totalPrice'].mean().\
sort_values(ascending=False).reset_index()
plt.figure(figsize=(12,8))
plt.tick_params(labelsize=16)
ax = sns.barplot(x='District', y='totalPrice', data=total_district, palette='Greens_r')
ax.set_title('杭州市各区房源平均总价对比', fontsize=20)
ax.set_xlabel('区域', fontsize=18)
ax.set_ylabel('总价/万元', fontsize=18)
ax.spines['right'].set_visible(False)
ax.spines['top'].set_visible(False)
for index, row in total_district.iterrows():ax.text(row.name,row.totalPrice+10, round(row.totalPrice), ha='center', fontsize=14)
来看看结果,滨江区最高,平均531万一套。不得不说,杭州人民真有钱。
使用pyecharts的Map,把它放到地图上看看。关于pyecharts和相应扩展地图的安装,可以参考这个。注意,地图上没有钱塘新区。
pair1 = [(row["District"], round(row["totalPrice"],2)) for i, row in total_district.iterrows()]
map1 = Map(init_opts=opts.InitOpts(theme='macarons', width='800px', height='400px'))
map1.add('杭州', pair1, '杭州',is_roam=False)
map1.set_series_opts(label_opts=opts.LabelOpts(is_show=False))
map1.set_global_opts(title_opts=opts.TitleOpts(title='杭州各区域房源平均总价对比'),legend_opts=opts.LegendOpts(is_show=False),visualmap_opts=opts.VisualMapOpts(min_=round(total_district['totalPrice'].min()), max_=round(total_district['totalPrice'].max())),tooltip_opts=opts.TooltipOpts(formatter='{b}:{c}万元') # a.为杭州,b为各区名称,c为价格
)
map1.render_notebook()
接下来,可以看看各个区域的直方图和核密度图,以便了解每个区域平均总房价的分布。
locations = df['District'].unique()
plt.figure(figsize=(18,12))
with sns.axes_style('ticks'): # 通过with,把subplot的风格设置为'ticks'for i in range(len(locations)):temp = df[df['District'] == locations[i]]plt.subplot(3,4,i+1)plt.title(locations[i])sns.distplot(temp['totalPrice'])plt.xlabel('')
plt.show()
可以发现,像钱塘新区,富阳区的价格分布有些正态分布的味了。而价格三巨头,滨江、西湖和上城区,都有些正偏态分布,即平均数大于众数。这说明,这几个地区的总房价里面有坏人,太高了![外链图片转存中…(img-Hh7Ir5yb-1600328097491)]](https://imgconvert.csdnimg.cn/aHR0cHM6Ly9pbWdjaHIuY29tL2kvd3UwUFBJ?x-oss-process=image/format,png)
再来看看箱线图,可能更直观一点:
plt.figure(figsize=(12,8))
plt.tick_params(labelsize=16)
axbox1 = sns.boxplot(x='District', y='totalPrice', data=df,)
axbox1.set_title('杭州市各区房源总价分布', fontsize=20)
axbox1.set_xlabel('区域', fontsize=18)
axbox1.set_ylabel('总价/万元', fontsize=18)
箱线图:
通过以上,我们可以发现,大部分区域二手房价格的中位数都在400万以下。上城区和滨江区的极端值都很高,价格在1400万左右,拉高了均值。
4.3 杭州市各区域房源平均单价对比
我们再来看见平均单价。
ave_district = df.groupby('District')['unitPrice'].mean().sort_values(ascending=False).reset_index()plt.figure(figsize=(12,8))
plt.tick_params(labelsize=16)
ax2 = sns.barplot(x='District', y='unitPrice', data=ave_district, palette='Blues_r')
ax2.spines['right'].set_visible(False)
ax2.spines['top'].set_visible(False)
ax2.set_title('杭州市各区房源平均单价对比', fontsize=20)
ax2.set_xlabel('区域', fontsize=18)
ax2.set_ylabel('单价/元', fontsize=18)
for index, row in ave_district.iterrows():ax2.text(row.name, row.unitPrice+500, round(row.unitPrice), ha='center', fontsize=14)
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-FVrnY2ZT-1600328097496)(https://s1.ax1x.com/2020/09/08/wQWu6g.png)]
看了之后,心哇凉哇凉的O(∩_∩)O哈哈~。再放到地图上看看。
pair2 = [(row.District,round(row.unitPrice,2)) for index, row in ave_district.iterrows()]map2 = Map(init_opts=opts.InitOpts(theme='macarons', width='800px', height='400px'))
map2.add('杭州', pair2, '杭州', is_roam=False)
map2.set_series_opts(label_opts=opts.LabelOpts(is_show=False))
map2.set_global_opts(title_opts = opts.TitleOpts(title='杭州市各区房源平均单价对比'),legend_opts = opts.LegendOpts(is_show=False),visualmap_opts = opts.VisualMapOpts(min_=round(ave_district['unitPrice'].min()), max_=round(ave_district['unitPrice'].max())),tooltip_opts = opts.TooltipOpts(formatter='{b}: {c}元')
)
map2.render_notebook()
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-h89mymKO-1600328097498)(https://s1.ax1x.com/2020/09/08/wQ5n5n.png)]
同样,看看各区域价格分布。可以看出,大多数区域房源单价的分布都是中间多。
plt.figure(figsize=(18, 12))
with sns.axes_style('ticks'):for i in range(len(locations)):temp = df[df['District'] == locations[i]]plt.subplot(3,4, i+1)plt.title(locations[i])sns.distplot(temp['unitPrice'])plt.xlabel('')plt.suptitle('杭州市各区房源平均单价分布', fontsize=18)plt.show()
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-XbVQuvno-1600328097499)(https://s1.ax1x.com/2020/09/08/wl9VNq.png)]
同样看一下箱线图:
plt.figure(figsize=(12, 8))
plt.tick_params(labelsize=16)
axbox2 = sns.boxplot(x='District', y='unitPrice', data=df, palette=sns.color_palette('muted'))
axbox2.set_xlabel('区域', fontsize=16)
axbox2.set_ylabel('单价/元', fontsize=16)
axbox2.set_title('杭州市各区房源单价分布', fontsize=18)
plt.show()
结果图:
可以看出,大多数区域房屋单价都在4万元每平米左右。真的是贵。
4.4 杭州市各区域房源关注度对比
看看关注度对比:
follow_district = df.groupby('District')['Follow'].sum().sort_values(ascending=False).reset_index()plt.figure(figsize=(12, 8))
plt.tick_params(labelsize=16)
ax3 = sns.barplot(x='District', y='Follow', data=follow_district, palette='Reds_r')
ax3.spines['top'].set_visible(False)
ax3.spines['right'].set_visible(False)
ax3.set_title('杭州市各区房源关注度对比', fontsize=18)
ax3.set_ylabel('关注人数', fontsize=16)
ax3.set_xlabel('区域', fontsize=16)
for index, row in follow_district.iterrows():ax3.text(row.name, row['Follow']+ 2000, row['Follow'], ha='center', fontsize=14)
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ZrSgLdYD-1600328097502)(https://s1.ax1x.com/2020/09/09/w1VERA.png)]
滨江区这个关注度一骑绝尘啊。
4.5 不同因素对关注度的影响
4.5.1 不同房型对关注度的影响
在前面,为了做相关,我们把Layout拆分成了Room和Hall两种变量。现在把它组合回来,然后再看看不同户型的关注度。
df['Layout'] = df['Room'].astype('str')+'室'+df['Hall'].astype('str')+'厅'
df['Layout'].unique()
共有以下几种房型:
array(['4室2厅', '2室2厅', '3室2厅', '3室1厅', '5室2厅', '2室1厅', '4室1厅', '1室1厅','6室2厅', '1室2厅', '1室0厅', '2室0厅', '5室1厅'], dtype=object)
看看关注度最高的10种房型:
layout_follow = df.groupby('Layout')['Follow'].sum().sort_values(ascending=False).reset_index()bar1 = Bar(init_opts=opts.InitOpts(theme='wonderland', width='800px', height='600px'))
bar1.add_xaxis(layout_follow['Layout'].head(10).to_list())
bar1.add_yaxis("", layout_follow['Follow'].head(10).to_list())
bar1.set_global_opts(title_opts=opts.TitleOpts(title='杭州市房源关注度TOP10', pos_left='center'))
# bar1.reversal_axis()
bar1.render_notebook()
结果如下:
3室2厅这么受欢迎的么。
4.5.2 不同朝向对关注度的影响
在这一部分,本来想做个玫瑰图,但类别太少了,而且类别差异过大,不太适合,所以就做个饼图吧。
ori_follow = df.groupby('Orientation')['Follow'].sum().sort_values(ascending=False).reset_index()pie = Pie(init_opts=opts.InitOpts(width='800px', height='450px', theme='light'))
pie.add("", [list(z) for z in zip(ori_follow['Orientation'], ori_follow['Follow'])],radius=['35%', '75%'],)
pie.set_global_opts(title_opts=opts.TitleOpts(title='不同朝向关注度对比'),legend_opts=opts.LegendOpts(is_show=True),toolbox_opts=opts.ToolboxOpts(is_show=False))
pie.set_series_opts(label_opts=opts.LabelOpts(is_show=True, font_size=12,formatter='{b}:{c}'))
pie.render_notebook()
结果如下:[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-OL0gklxM-1600328097506)(https://s1.ax1x.com/2020/09/10/wGGcS1.png)]
房屋朝南关注度最高。
4.5.3 楼层位置对关注度的影响
先观察下楼层位置的范围:
array([ 6, 5, 33, 32, 9, 14, 30, 19, 26, 11, 18, 12, 34, 16, 31, 20, 23,25, 2, 7, 27, 24, 3, 17, 28, 15, 8, 22, 10, 29, 42, 38, 43, 21,4, 13], dtype=int64)
最小的2,最大的是42。那么我们就可以从0~45,5层一组,共分为9组。
cut_range = [x for x in range(0,46, 5)]
cut_name = [str(cut_range[i]) + '-' + str(cut_range[i+1]) + '层' for i in range(9)]
df['floorRange'] = pd.cut(df['totalFloor'], cut_range, labels=cut_name)
接下来做可视化:
floor_follow = df.groupby('floorRange')['Follow'].sum().sort_values(ascending=False).reset_index()bar2 = Bar(init_opts=opts.InitOpts(theme='vintage', width='600px', height='400px'))
bar2.add_xaxis(floor_follow['floorRange'].to_list())
bar2.add_yaxis("关注度", floor_follow['Follow'].to_list())
bar2.set_series_opts(label_opts=opts.LabelOpts(is_show=True))
bar2.set_global_opts(title_opts=opts.TitleOpts(title='不同楼层关注度'), xaxis_opts=opts.AxisOpts(axislabel_opts={'rotate': 45,}))
bar2.render_notebook()
结果如下。
看来大家比较倾向于中低楼层。但0~5的关注度也不高。
4.5.4 装修情况对关注度的影响
装修有精装、简装和毛坯三种。看看这几种装修情况的关注度如何。
reno_follow = df.groupby('Renovation')['Follow'].sum().sort_values(ascending=False).reset_index()bar3 = Bar(init_opts=opts.InitOpts(theme='roma', width='700px', height='300px'))
bar3.add_xaxis(reno_follow['Renovation'].to_list())
bar3.add_yaxis("装修情况", reno_follow['Follow'].to_list())
bar3.set_series_opts(label_opts=opts.LabelOpts(is_show=True, position='right'))
bar3.set_global_opts(title_opts=opts.TitleOpts('装修情况对关注度的影响'), xaxis_opts=opts.AxisOpts(axislabel_opts={'interval':"0"}))bar3.reversal_axis()
bar3.render_notebook()
结果如图:
看来大家都比较喜欢精装的房子。
4.6 杭州市各区房源面积对比
再看一下面积:
size_district = df.groupby('District')['Size'].mean().sort_values(ascending=True).reset_index()bar3 = Bar(init_opts=opts.InitOpts(theme='vintage', width='800px', height='600px'))
bar3.add_xaxis(size_district['District'].to_list())
bar3.add_yaxis("平均面积", round(size_district['Size'],2).to_list())
bar3.set_series_opts(label_opts=opts.LabelOpts(is_show=True, position='right'))
bar3.set_global_opts(title_opts=opts.TitleOpts("杭州市各区房源平均面积对比"),xaxis_opts=opts.AxisOpts(axislabel_opts={'interval': "0"}))bar3.reversal_axis()
bar3.render_notebook()
结果如图
平均下来之后,都没有超过120平米。再看一下总体面积分布。
f,[ax1, ax2] = plt.subplots(1,2,figsize=(18,6))
sns.distplot(df['Size'],ax=ax1, rug=True, bins=20)
ax1.set_title('杭州市各区房源面积分布', fontsize=18)
ax1.tick_params(labelsize=14)
sns.regplot(x='Size', y='totalPrice', data=df, ax=ax2)
ax2.set_title('房屋总价和面积关系', fontsize=18)
ax2.tick_params(labelsize=14)
ax2.set_xlabel('房屋面积/㎡', fontsize=16)
ax2.set_ylabel('房屋总价/万元', fontsize=16)
plt.show()
看看结果图:
可以看出:
- 绝大多数房屋面积都在100平米左右,最大的在250平米以上。
- 房屋面积和总价格成正相关(一个有点废话的结论,O(∩_∩)O)。
5 总结
5.1 结论
- 杭州二手房市场价格较贵。大多数区域房源总体价格中位数在400万左右,单价中位数在4万元每平方。
- 杭州二手房热度和价格都较高的区域为:滨江区、西湖区,拱墅区和上城区。其中,滨江区在热度和总价方面都最高,而在单价方面却小于其他三区,原因是因为该区二手房平均面积较大。同时,从整体数据来看,房屋价格和面积呈正相关。
- 本次分析主要是想巩固以下python的可视化,主要用到的有条形图、饼图、地图、和密度分布。Python在作图这方面,不管是图类型还是样式,离ggplot2的差距越来越小。
5.2 待改进
- 在处理房屋朝向时,过于简单,有点混乱,后续可以改进。
- 可以加入机器学习的部分,预测二手房价格。
Update Log
- 2020-09-01 17:11:21,爬取数据
- 2020-09-04 20:09:38,完成平均总房价分析
- 2020-09-07 18:53:00,发现房子的“关注度”指标有分析价值,重新爬取数据
- 2020-09-10 17:07:51,数据可视化完成。
2020链家杭州二手房数据分析(截止到2020年09月07日)相关推荐
- 用Python爬取2020链家杭州二手房数据
起源于数据挖掘课程设计的需求,参考着17年这位老兄写的代码:https://blog.csdn.net/sinat_36772813/article/details/73497956?utm_medi ...
- 爬虫+可视化——链家杭州二手房房源信息
------------本篇文章旨在练习数据的爬取及可视化 简介 本项目分两个部分: 1.爬虫:共爬取到链家杭州二手房信息30806条 2.可视化:主要用pyecharts 一.获取数据 提取杭州各个 ...
- 链家网二手房数据分析(承接上篇爬虫)
import pandas as pd import numpy as np import matplotlib.pyplot as plt plt.rcParams['font.sans-serif ...
- 数据分析:pandas分析链家网二手房信息
分析链家网南京市二手房信息 链家网二手房数据的采集方法参见之前的博客:数据采集(四):用XPath爬取链家网房价数据 总共有3000条二手房信息记录. import pandas as pd impo ...
- python爬虫requests源码链家_python的爬虫项目(链家买二手房)
不知不觉,已经工作6年有余,恍恍惚惚,有机会满足房子需求. 在收集房子信息过程中,做些记录. 贝壳的功能很强大,但很难满足小区.距离.教育.面积等多个方面的匹配,使用起来成本仍然较高. 针对以上情况, ...
- python爬取链家新房_Python爬虫实战:爬取链家网二手房数据
前言 本文的文字及图片来源于网络,仅供学习.交流使用,不具有任何商业用途,如有问题请及时联系我们以作处理. 买房装修,是每个人都要经历的重要事情之一.相对于新房交易市场来说,如今的二手房交易市场一点也 ...
- python二手房使用教程_python实战:基于链家网二手房数据解析任务
实战:基于链家网二手房数据解析任务 页面:https://bd.ke.com/ershoufang/ 获取如下信息: 标题 位置 房屋信息 关注人数 / 发布时间 房屋总价 房屋单价 备注信息 1.导 ...
- 使用Java及jsoup爬取链家北京二手房房价数据
由于是初次使用Java写爬虫,所以代码有些繁琐,请大家见谅,并能给与指正 首先分析链家北京二手房页面,使用360浏览器的审查元素功能,查看源代码,获取查询标签 如图一级查询所示,此图标签所获取的是链家 ...
- 关于链家全网房价数据分析挖掘项目
**关于链家全网房价数据分析挖掘项目** 数据说明 数据信息: 数据量:40多万条观测,20多个列变量 时间:2018年5月前 数据来源 作者:田昕峣 获取方式:https://github.com/ ...
最新文章
- MySQL - 索引优化案例实操
- 云时代的智能运维平台,助力企业创新迭代
- 从零开始学JavaWeb
- transactional注解的使用_Java:Spring @Transactional工作原理
- 根据经纬度求最近点的三种解法java实现
- 虚拟化精华问答 | 什么是虚拟化?
- 踏青旅行必备的民宿指南,都在这些airbnb数据里了
- Android打开App2SD
- 序列化和反序列化(五)——敏感字段加密
- 踏实学习前端,学技术,必有高薪,好的人生,学习量大能力要求高就对了
- ArcGIS for iOS 开发系列(3) – 基础篇-“Hello World Map”
- 4款好用流程图软件,都是经验总结出来的
- 计算机除了冯诺依曼架构,什么是实用的非冯·诺依曼架构?
- 阿里、京东、亚马逊为何如此重视重构“会员”?
- 两款浏览器去广告插件,让你舒心上网
- 江苏大学 操作系统 知识点提纲 期末考试/考研 复习
- (附源码)计算机毕业设计ssm高校教材管理系统
- 使用useState因异步导致数据不能及时更新的问题
- 你好世界在Java语言中的编程代码
- 转: 云计算openstack—云计算、大数据、人工智能