作者:J哥
背景
香港的贫富差距问题一直十分尖锐,最突出的体现就是收入和楼价的巨大差异。早在60年代末香港房价就经历了暴涨,人们早已对不动产的金融属性了如指掌,全港的投资情绪一直都相当火热。
即便香港当前失业率高企,经济环境较差,但购买力仍在,楼市依然坚挺。
为了更加深入了解香港房地产市场,本文用Pyhton采集了香港在售26281套二手房数据并做可视化分析,试图从数据层面理解香港楼市现状。
具体代码详解见本文后半段,数据分析代码和数据集可在公众号【凹凸数据】后台回复「香港」即可获取。
九龙房源最多,港岛价格更高
香港特别行政区,下辖香港岛、九龙半岛、新界3个地区共18个分区。九龙半岛在售二手房源共8108个,占比28.62%。根据中原城市指数CCI(仅包括大型屋苑),港岛报187.66点,高于香港其他地区。
具体分区来看,香港在售二手房源集中分布在葵青区、元朗区、屯门区等地,而九龙城区、深水埗区、中西区、湾仔区、东区等地房价较高。香港在售二手房实用呎价均价为 呎 ( 折 合 人 民 币 约 元 平 方 米 ) , 最 低 实 用 呎 价 4421/呎,最高实用呎价$96965/呎。
将军澳二手房源最多
将军澳、元朗和屯门在售二手房均超1000套,其中,将军澳以2112套二手房源居首。
九龙站二手房均价最高
九龙站、山顶/南区、贝沙湾和中半山在售二手房均价超过 万 呎 , 九 龙 站 以 37232/呎遥遥领先,远高于香港二手房整体均价。
小户型为主,2房占比超一半
从建筑面积来看,香港在售二手房普遍建面在500呎-1200呎(46-111平方米),占比高达78.52%,共计18825套。
从居室来看,香港在售二手房中,2房共计12231套,占比51.05%;3房共计7613套,占比31.76%;4房以上71套,占比仅为0.29%。
各楼龄段均有一定比例分布
从香港在售二手房楼龄来看,25-39年楼龄的二手房源最多,共7396套,占比31.31%;15-24年5939套,占比25.36%;40年以上房源也有2347套,占比10.93%。
50%以上二手房低于1000万
从香港在售二手房售价来看, 1000万(约429-858万人民币)房源数量为12301套,占比51.31%。
描述性统计
相关性分析
从相关系数表和回归图来看,间隔(即居室)和楼龄都与香港二手房房价无明显的相关性。实用面积与房价具有较强的正相关性,一般来说,人们在看房子时看到的面积是建筑面积,但却不是实用面积。套内建筑面积=套内使用面积+套内墙体面积+阳台面积,而实用面积就是套内使用面积。另外,实用率与房价也无相关性,这与大部分人的感性认识存在偏差。
技术实现
本文数据来源于中原地产,网页结构相对简单。数据清洗主要用到Python的pandas库,由于内容较多,仅提供核心字段清洗代码。数据可视化主要用到Python的pyecharts
库,都是一些基础图表,本公众号往期原创文章也已多次提及。
数据获取
爬虫核心代码
#将繁体转换成简体def tradition2simple(line): return Converter('zh-hans').convert(line)#解析网页def get_page(page): if page <11: url = 'http://hk.centanet.com/findproperty/BLL/Result_SearchHandler.ashx?url=http%3A%2F%2Fhk.centanet.com%2Ffindproperty%2Fzh-HK%2FHome%2FSearchResult%3Fposttype%3DS%26src%3DC%26minprice%3D%26maxprice%3D%26sortcolumn%3D%26sorttype%3D%26limit%3D100%26currentpage%3D{0}'.format(page) else: url = 'http://hk.centanet.com/findproperty/BLL/Result_SearchHandler.ashx?url=http%3A%2F%2Fhk.centanet.com%2Ffindproperty%2Fzh-HK%2FHome%2FSearchResult%3Fposttype%3DS%26src%3DC%26minprice%3D%26maxprice%3D%26sortcolumn%3D%26sorttype%3D%26limit%3D-1%26currentpage%3D{0}'.format(page) req = requests.get(url, headers = headers) bs = req.json() # print(bs) ts = tradition2simple(bs['post']) # print(ts) html = etree.HTML(ts)if __name__ == '__main__': ua = UserAgent(verify_ssl=False) headers = {"User-Agent": ua.random} for page in range(1,2624): #共2623页 get_page(page) # time.sleep(1) print("第%d页爬取完成"%page) print('-'*100)
数据预览
数据清洗
建筑面积/单价
#异常字符替换为空df["建筑面积"] = df["建筑面积"].str.replace(",","").astype("float")df["建面单价"] = df["建面单价"].str.replace("$","").str.replace(",","").str.replace("/呎","").astype("float")#建筑面积和建面单价缺失值用均值填充df = df.fillna(value={'建筑面积':df["建筑面积"].mean(),'建面单价':df["建面单价"].mean()})
间隔
# 存在缺失值、换行符、非数字型、无房间数等脏数据df["间隔"] = df["间隔"].str.replace("\r\n","").str[:1]df = df[ ~ df['间隔'].isin(['('])] #删除某列包含特殊字符的行df["间隔"] = df["间隔"].str.replace("开","0").astype("float")df = df.fillna(value={'间隔':df["间隔"].mean()})df["间隔"] = df["间隔"].astype("int")
售价
#售价单位存在万和亿,进行统一化处理df["售价"] = (df["售价"].str.replace("$","").str.replace(",","").str[:-1].astype(float) * df['售价'].str[-1].map({"万": 1, "亿": 10000})).astype("int")
数据可视化
回归图
fig,axes=plt.subplots(5,1,figsize=(12,30)) sns.regplot(x='间隔',y='实用单价',data=df1,color='green',marker='*',ax=axes[0])sns.regplot(x='楼龄',y='实用单价',data=df1,color='green',marker='*',ax=axes[1])sns.regplot(x='实用面积',y='实用单价',data=df1,color='green',marker='*',ax=axes[2])sns.regplot(x='建筑面积',y='实用单价',data=df1,color='green',marker='*',ax=axes[3])sns.regplot(x='实用率',y='实用单价',data=df1,color='green',marker='*',ax=axes[4])
条形图
df5 = df1.groupby('屋苑位置')['实用单价'].count()df5 = df5.sort_values(ascending=True)df5 = df5.tail(10)print(df5.index.to_list())print(df5.to_list())c = ( Bar(init_opts=opts.InitOpts(theme=ThemeType.WONDERLAND)) .add_xaxis(df5.index.to_list()) .add_yaxis("",df5.to_list()).reversal_axis() #X轴与y轴调换顺序 .set_global_opts(title_opts=opts.TitleOpts(title="香港二手房数量TOP10",subtitle="数据来源:中原地产 \t制图:J哥",pos_left = 'left'), xaxis_opts=opts.AxisOpts(axislabel_opts=opts.LabelOpts(font_size=13)), #更改横坐标字体大小 yaxis_opts=opts.AxisOpts(axislabel_opts=opts.LabelOpts(font_size=13)), #更改纵坐标字体大小 ) .set_series_opts(label_opts=opts.LabelOpts(font_size=16,position='right')) )c.render_notebook()
饼图
df2 = df1.groupby('间隔')['实用单价'].count()print(df2)df2 = df2.sort_values(ascending=False) regions = df2.index.to_list()values = df2.to_list()c = ( Pie(init_opts=opts.InitOpts(theme=ThemeType.WONDERLAND)) .add("", list(zip(regions,values))) .set_global_opts(title_opts=opts.TitleOpts(title="香港二手房间隔分布",subtitle="数据来源:中原地产\n制图:J哥",pos_top="1%",pos_left = 'left')) .set_series_opts(label_opts=opts.LabelOpts(formatter="{b}:{d}%",font_size=16)) )c.render_notebook()
凹凸福利
推荐语📕:《Python数据可视化:基于Bokeh的可视化绘图》这是一本适合零基础读者快速入门并掌握Bokeh的实战指南,作者是Bokeh的先驱用户和布道者,实践经验丰富。本书从图形绘制、数据动态展示、Web交互等维度全面讲解Bokeh功能和使用,不涉及复杂的数据处理和算法,包含大量实战案例。点击下图可看详情/购买!👇
感谢机械工业出版社华章公司的支持! 「凹凸数据」 300积分 兑换🎁!
当当限时购书优惠码: *HSMQ9J* ,自营 100-20 ; FWJY6Q ,自营 49-20 (限新客,换个手机号即可) 以上优惠券均可叠加满100-50活 动
本文分享自微信公众号 - 凹凸数据(alltodata)。
如有侵权,请联系 support@oschina.cn 删除。
本文参与“OSC源创计划”,欢迎正在阅读的你也加入,一起分享。