用Python分析北京市蛋壳公寓租房数据

Karen110 等级 469 0 0

前言


大家好,我是J哥。

近期,蛋壳公寓“爆雷”事件持续发酵,期间因拖欠房东房租与租客退款,蛋壳公寓陷入讨债风波,全国多地蛋壳公寓办公区域出现大规模解约事件,而作为蛋壳公寓总部所在地北京,自然首当其冲。

为了应对大规模的解约,北京在全市已经设立了100多个蛋壳公寓矛盾纠纷接待点,包含了蛋壳公寓涉及到的12个区,这些接待点下沉到了街道甚至社区,以方便涉及蛋壳公寓事件的房东和租客咨询和处理纠纷。

长租公寓暴雷,不少年轻人不得不流离失所,构成疫情下的另一个经济写照,事态何去何从,值得关注。本文从数据角度出发,爬取了蛋壳公寓北京区域共6025条公寓数据,清洗数据,并进行可视化分析,为大家了解蛋壳公寓提供一个新的视角。后台回复 「北京蛋壳」 可获取本文数据分析数据集。

数据获取

蛋壳公寓网页结构相对简单,数据结构统一,简单的url翻页构造即可。需要注意的是极少数网页会返回404,需要添加判断过滤掉。本文用request请求到数据,用xpath对返回的数据进行解析,最后以追加模式将数据存储为csv文件。爬虫核心代码如下:

def get_danke(href):  
    time.sleep(random.uniform(0, 1))  #设置延时,避免对服务器产生压力  
    response = requests.get(url=href, headers=headers)  
    if response.status_code == 200:  #部分网页会跳转404,需要做判断  
        res = response.content.decode('utf-8')  
        div = etree.HTML(res)  
        items = div.xpath("/html/body/div[3]/div[1]/div[2]/div[2]")  
        for item in items:  
            house_price=item.xpath("./div[3]/div[2]/div/span/div/text()")[0]  
            house_area=item.xpath("./div[4]/div[1]/div[1]/label/text()")[0].replace('建筑面积:约','').replace('㎡(以现场勘察为准)','')  
            house_id=item.xpath("./div[4]/div[1]/div[2]/label/text()")[0].replace('编号:','')  
            house_type=item.xpath("./div[4]/div[1]/div[3]/label/text()")[0].replace('\n','').replace(' ','').replace('户型:','')  
            house_floor=item.xpath("./div[4]/div[2]/div[3]/label/text()")[0].replace('楼层:','')  
            house_postion_1=item.xpath("./div[4]/div[2]/div[4]/label/div/a[1]/text()")[0]  
            house_postion_2=item.xpath("./div[4]/div[2]/div[4]/label/div/a[2]/text()")[0]  
            house_postion_3=item.xpath("./div[4]/div[2]/div[4]/label/div/a[3]/text()")[0]  
            house_subway=item.xpath("./div[4]/div[2]/div[5]/label/text()")[0]  
    else:  
        house_price = None  
        house_area = None  
        house_id = None  
        house_type = None  
        house_floor = None  
        house_postion_1 = None  
        house_postion_2 = None  
        house_postion_3 = None  
        house_subway = None  
......  

由于代码运行过程中中断了几次,最终将数据保存为以下几个csv文件中:用Python分析北京市蛋壳公寓租房数据

数据处理

导入数据分析包

import pandas as pd  
import numpy as np  
from pathlib import Path  
import re  

导入数据并合并

找到文件夹中的所有csv文件,遍历读取数据,最后用concat方法合并所有数据。

files = Path(r"D:\菜J学Python\数据分析\蛋壳公寓").glob("*.csv")  
dfs = [pd.read_csv(f) for f in files]  
df = pd.concat(dfs)  
df.head()  

用Python分析北京市蛋壳公寓租房数据

数据去重

数据爬取过程中有中断,因此可能存在重复爬取的情况,需要去重处理。

df = df.drop_duplicates()  

查看数据

用df.info()方法查看整体数据信息,结合预览的数据,我们可以很容易发现,价格和面积字段不是数字类型,需要转换处理。楼层字段可以提取出所在楼层和总楼层。

df.info()  
 <class 'pandas.core.frame.DataFrame'>  
    Int64Index: 6026 entries, 0 to 710  
    Data columns (total 9 columns):  
     #   Column  Non-Null Count  Dtype   
    ---  ------  --------------  -----   
     0   价格      6025 non-null   object  
     1   面积      6025 non-null   object  
     2   编号      6025 non-null   object  
     3   户型      6025 non-null   object  
     4   楼层      6025 non-null   object  
     5   位置1     6025 non-null   object  
     6   位置2     6025 non-null   object  
     7   小区      6025 non-null   object  
     8   地铁      6025 non-null   object  
    dtypes: object(9)  
    memory usage: 470.8+ KB

数据类型转换

在字段类型转换时报错,检查发现是数据存在一行脏数据,因此先删除脏数据再做转换即可。数据类型转换用到astype()方法,提取所在楼层和总楼层时根据字符"/"分列即可,采用split()方法。

#删除包含脏数据的行  
jg = df['价格'] != "价格"   
df = df.loc[jg,:]  

#将价格字段转为数字类型  
df["价格"] = df["价格"].astype("float64")  

#将面积字段转为数字类型  
df["面积"] = df["面积"].astype("float64")  

#提取所在楼层  
df = df[df['楼层'].notnull()]  
df['所在楼层']=df['楼层'].apply(lambda x:x.split('/')[0])  
df['所在楼层'] = df['所在楼层'].astype("int32")  

#提取总楼层  
df['总楼层']=df['楼层'].apply(lambda x:x.split('/')[1])  
df['总楼层'] = df['总楼层'].str.replace("层","").astype("int32")  

地铁字段清洗

地铁字段可以提取出地铁数和距离地铁距离。地铁数通过统计字符"号线”的数量来计算,而距离地铁距离通过正则表达式匹配出字符"米"前面的数字即可。为方便理解,这里直接构造函数进行清洗。

def get_subway_num(row):  
    subway_num=row.count('号线')  
    return subway_num  

def get_subway_distance(row):  
    distance=re.search(r'\d+(?=米)',row)  
    if distance==None:  
        return-1  
    else:  
        return distance.group()  
df['地铁数']=df['地铁'].apply(get_subway_num)  
df['距离地铁距离']=df['地铁'].apply(get_subway_distance)  
df['距离地铁距离']=df['距离地铁距离'].astype("int32")  

保存数据

数据清洗完毕后,用df.to_excel()将数据保存为excel文件。

df.to_excel(r"\菜J学Python\数据分析\蛋壳公寓.xlsx")  
df.head()  

用Python分析北京市蛋壳公寓租房数据

数据可视化

导入可视化相关包

import matplotlib.pyplot as plt  
import seaborn as sns  
%matplotlib inline  
plt.rcParams['font.sans-serif'] = ['SimHei']  # 设置加载的字体名  
plt.rcParams['axes.unicode_minus'] = False# 解决保存图像是负号'-'显示为方块的问题   
import jieba  
from pyecharts.charts import *  
from pyecharts import options as opts   
from pyecharts.globals import ThemeType    
import stylecloud  
from IPython.display import Image  

各行政区公寓数量

根据清洗后的数据绘制北京蛋壳公寓分布地图,我们可以很清晰的看到蛋壳公寓的布局,朝阳区和通州区是蛋壳公寓主要分布区域,延庆、密云、怀柔、平谷和门头沟地区蛋壳公寓分布极少。用Python分析北京市蛋壳公寓租房数据从各行政区数量上来看,朝阳区和通州区蛋壳公寓数量均超过1000个,朝阳区遥遥领先其他地区,共计1877个,通州区紧随其后,为1027个。

df7 = df["位置1"].value_counts()[:10]  
df7 = df7.sort_values(ascending=True)  
df7 = df7.tail(10)  
print(df7.index.to_list())  
print(df7.to_list())  
c = (  
    Bar(init_opts=opts.InitOpts(theme=ThemeType.DARK))  
    .add_xaxis(df7.index.to_list())  
    .add_yaxis("",df7.to_list()).reversal_axis() #X轴与y轴调换顺序  
    .set_global_opts(title_opts=opts.TitleOpts(title="各行政区公寓数量",subtitle="数据来源:蛋壳公寓 \t制图:菜J学Python",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()  

用Python分析北京市蛋壳公寓租房数据

小区公寓数量TOP10

从小区数量来看,新建村小区、花香东苑和连心园西区蛋壳公寓数量最多,均超过50个。这也意味着,这些小区的租户受蛋壳风波的影响相较于其他小区更大。

df7 = df["小区"].value_counts()[:10]  
df7 = df7.sort_values(ascending=True)  
df7 = df7.tail(10)  
print(df7.index.to_list())  
print(df7.to_list())  
c = (  
    Bar(init_opts=opts.InitOpts(theme=ThemeType.DARK,width="1100px",height="600px"))  
    .add_xaxis(df7.index.to_list())  
    .add_yaxis("",df7.to_list()).reversal_axis() #X轴与y轴调换顺序  
    .set_global_opts(title_opts=opts.TitleOpts(title="小区公寓数量TOP10",subtitle="数据来源:蛋壳公寓 \t制图:菜J学Python",pos_left = 'left'),  
                       xaxis_opts=opts.AxisOpts(axislabel_opts=opts.LabelOpts(font_size=11)), #更改横坐标字体大小  
                       yaxis_opts=opts.AxisOpts(axislabel_opts={"rotate":30}), #更改纵坐标字体大小  
                       )  
    .set_series_opts(label_opts=opts.LabelOpts(font_size=16,position='right'))  
    )  
c.render_notebook()  

用Python分析北京市蛋壳公寓租房数据

蛋壳公寓租金分布

对租金进行区间分段,我们发现,北京蛋壳公寓的租金还是相当有吸引力的,超过一半的公寓租金在2000-3000元/月。2000元/月以下的公寓数量占比也高达26.13%。

#租金分段  
df['租金分段'] = pd.cut(df['价格'],[0,1000,2000,3000,4000,1000000],labels=['1000元以下','1000-2000元','2000-3000元','3000-4000元','4000元以上'],right=False)  
df11 = df["租金分段"].value_counts()  
df11 = df11.sort_values(ascending=False)  
df11 = df11.round(2)  
print(df11)  
c = (  
        Pie(init_opts=opts.InitOpts(theme=ThemeType.DARK))  
        .add(  
            "",  
            [list(z) for z in zip(df11.index.to_list(),df11.to_list())],  
            radius=["20%", "80%"],   #圆环的粗细和大小  
            rosetype='area'  

        )  
        .set_global_opts(legend_opts = opts.LegendOpts(is_show = False),title_opts=opts.TitleOpts(title="蛋壳公寓租金分布",subtitle="数据来源:蛋壳公寓\n制图:菜J学Python",pos_top="0.5%",pos_left = 'left'))  
        .set_series_opts(label_opts=opts.LabelOpts(formatter="{b}:{d}%",font_size=16))  
    )  
c.render_notebook()  

用Python分析北京市蛋壳公寓租房数据

各行政区租金分布

我们继续将地区因素引入租金分析中,发现,不同行政区内的租金分布也存在较大差异。以朝阳区为例,2000-3000元/月的公寓占比最多,而通州区1000-2000元/月的公寓占比更多。这也很容易理解,毕竟所处的区位和经济发展状况差异较大。

h = pd.pivot_table(df,index=['租金分段'],values=['价格'],  
               columns=['位置1'],aggfunc=['count'])  
k = h.droplevel([0,1],axis=1)  #删除指定的索引/列级别  
c = (  
    Polar(init_opts=opts.InitOpts(theme=ThemeType.DARK))  
    .add_schema(angleaxis_opts=opts.AngleAxisOpts(data=k.columns.tolist(), type_="category"))  
    .add("1000以下",h.values.tolist()[0], type_="bar", stack="stack0")  
    .add("1000-2000元",h.values.tolist()[1], type_="bar", stack="stack0")  
    .add("2000-3000元", h.values.tolist()[2], type_="bar", stack="stack0")  
    .add("3000-4000元", h.values.tolist()[3], type_="bar", stack="stack0")  
    .add("4000元以上", h.values.tolist()[4], type_="bar", stack="stack0")  
    .set_global_opts(title_opts=opts.TitleOpts(title="各行政区租金情况",subtitle="数据来源:蛋壳公寓\n制图:菜J学Python"))  

)  
c.render_notebook()  

用Python分析北京市蛋壳公寓租房数据

蛋壳公寓楼层分布

从北京蛋壳公寓的楼层分布来看,10层以下占比高达73.92,高层和超高层不是蛋壳公寓的理想选择。

# 漏斗图   
df['楼层分段'] = pd.cut(df['所在楼层'],[0,10,20,30,40,1000000],labels=['10层以下','10-20层','20-30层','30-40层','40层以上'],right=False)  
count = df['楼层分段'].value_counts() # pd.Series  
print(count)  
job = list(count.index)  
job_count = count.values.tolist()  
from pyecharts.charts import Funnel  

c = (  
    Funnel(init_opts=opts.InitOpts(theme=ThemeType.DARK))  
    .add("", [list(i) for i in zip(job,job_count)])  
    .set_global_opts(  
        title_opts=opts.TitleOpts(title="蛋壳公寓楼层分布",subtitle="数据来源:蛋壳公寓\n制图:菜J学Python",pos_top="0.1%",pos_left = 'left'),legend_opts = opts.LegendOpts(is_show = False))  
    .set_series_opts(label_opts=opts.LabelOpts(formatter="{b}:{d}%",font_size=16))  
)  
c.render_notebook()  

用Python分析北京市蛋壳公寓租房数据

蛋壳公寓户型分布

从北京蛋壳公寓的户型分布来看,3室1卫为主,共计2783个,其次才是4室1卫。这与深圳蛋壳公寓以4室1卫为主的情况存在较大差异。

df2 = df.groupby('户型')['价格'].count()   
df2 = df2.sort_values(ascending=False)[:10]  
# print(df2)  
bar = Bar(init_opts=opts.InitOpts(theme=ThemeType.DARK))  
bar.add_xaxis(df2.index.to_list())  
bar.add_yaxis("",df2.to_list()) #X轴与y轴调换顺序  
bar.set_global_opts(title_opts=opts.TitleOpts(title="蛋壳公寓户型分布",subtitle="数据来源:蛋壳公寓\t制图:菜J学Python",pos_top="2%",pos_left = 'center'),  
                   xaxis_opts=opts.AxisOpts(axislabel_opts=opts.LabelOpts(font_size=16)), #更改横坐标字体大小  
                   yaxis_opts=opts.AxisOpts(axislabel_opts=opts.LabelOpts(font_size=16)), #更改纵坐标字体大小  
                   )  
bar.set_series_opts(label_opts=opts.LabelOpts(font_size=16,position='top'))  
bar.render_notebook()  

用Python分析北京市蛋壳公寓租房数据

蛋壳公寓面积分布

从北京蛋壳公寓的面积分布来看,86.77%的公寓面积不足20㎡。北京10㎡以下的蛋壳公寓占比达到了21.2%,即便如此,这个数字仍不足深圳的一半。

df['面积分段'] = pd.cut(df['面积'],[0,10,20,30,40,1000000],labels=['10㎡以下','10-20㎡','20-30㎡','30-40㎡','40㎡以上'],right=False)  
df2 = df["面积分段"].astype("str").value_counts()  
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.DARK))  
        .add("", list(zip(regions,values)))  
        .set_global_opts(legend_opts = opts.LegendOpts(is_show = False),title_opts=opts.TitleOpts(title="蛋壳公寓面积分布",subtitle="数据来源:蛋壳公寓\n制图:菜J学Python",pos_top="0.5%",pos_left = 'left'))  
        .set_series_opts(label_opts=opts.LabelOpts(formatter="{b}:{d}%",font_size=14))  

    )  
c.render_notebook()  

用Python分析北京市蛋壳公寓租房数据

蛋壳公寓商圈分布

通过对北京几个主要行政区商圈进行词云统计(字体越大表示蛋壳公寓数量最多),朝阳区的管庄、望京,通州区的北关,丰台区的樊羊路、方庄和角门,昌平区的天通苑,海淀区的永丰和西二旗,大兴区的黄村和亦庄,是蛋壳公寓主要选择的商圈。

# 绘制词云图  
text1 = get_cut_words(content_series=df1['位置2'])  
stylecloud.gen_stylecloud(text=' '.join(text1), max_words=100,  
                          collocations=False,  
                          font_path=r'C:\WINDOWS\FONTS\MSYH.TTC',  
                          icon_name='fas fa-home',  
                          size=653,  
                          palette='cartocolors.diverging.ArmyRose_2',  
                          output_name='./1.png')  
Image(filename='./1.png')  

用Python分析北京市蛋壳公寓租房数据

相关性分析

从相关系数表可以看出,北京蛋壳公寓的面积、周边地铁数对公寓的价格有较大的的影响,相关系数分别为0.81和0.36。蛋壳公寓在进行房屋定价时,对公寓的面积以及公寓的地铁配套有较大权重的考虑。由于北京蛋壳公寓距离地铁都很近,因此,距离的远近对公寓的价格影响有限。另外,所在楼层也不是北京蛋壳公寓租金高低的重要影响因素。

color_map = sns.light_palette('orange', as_cmap=True)  #light_palette调色板  
df.corr().style.background_gradient(color_map)  

用Python分析北京市蛋壳公寓租房数据

最后,愿所有受蛋壳公寓“暴雷”事件影响的年轻人都能熬过这个寒冬。

**-----**------**-----**---**** 送书 **-----**--------**-----**-****

内容简介

1、《Python网络爬虫开发从入门到精通》,内容如书名,欢迎大家前来取书,共送2本书。

用Python分析北京市蛋壳公寓租房数据

活动规则

参与方式:在本公众号后台回复 “送书”关键字,记得是“送书”二字哈,即可参与本次的送书活动。

公布时间:2020年12月16号(周三)晚上20点

领取事宜:请小伙伴添加小助手微信: pycharm1314,或者扫码添加好友。添加小助手的每一个人都可以领取一份Python学习资料,更重要的是方便联系。

用Python分析北京市蛋壳公寓租房数据

注意事项:一定要留意微信消息,如果你是幸运儿就尽快在小程序中填写收货地址、书籍信息。一天之内没有填写收货信息,送书名额就转给其他人了噢,欢迎参与~

**-----**------**-----**---**** End **-----**--------**-----**-****

往期精彩文章推荐:

用Python分析北京市蛋壳公寓租房数据

欢迎各位大佬点击链接加入群聊【helloworld开发者社区】:https://jq.qq.com/?_wv=1027&k=mBlk6nzX进群交流IT技术热点。

本文转自 https://mp.weixin.qq.com/s/33ReHjXD7X9Zz1VGZyYeMQ,如有侵权,请联系删除。

收藏
评论区

相关推荐

同学,你这简历上没项目啊!
大家好,我是小五 同学,刚毕业或者转行去求职数据分析师的时候,你遭遇过这样的尴尬怪圈吗? (https://imghelloworld.osscnbei
一文搞懂什么是HTTP与HTTPS
(https://blog.csdn.net/petterp/article/details/102779257)Http与Https的区别。 在最近的开发中,深感网络相关基础知识薄弱,于是趁周末好好总结一
15. Python 程序运行速度如何提高十倍?第一遍滚雪球学 Python 收工
本篇文章将给大家介绍 Python 多线程与多进程相关知识,学习完该知识点之后,你的 Python 程序将进入另一个高峰。 <center<font colorred缓解一下视疲劳</font</center 15. Python 程序运行速度如何提高十倍?第一遍滚雪球学 Python 收工(https://imghelloworld.oss
天猫双11数据过于完美?我们用python来看看
↑关注置顶 有趣的不像个技术号 是否真的完美? 双11结束了,大家已经无手可剁 。 天猫官方公布了今年的双11成交额为2684亿元,成
被“词云”包围的冰冰会更好看吗?安排
(https://imghelloworld.osscnbeijing.aliyuncs.com/b299933deefc692934e8cc6141ab3894.png) 大家好,我是小五🐶 昨天「凹凸数据」发了一篇张同学投稿的文章《用Python爬取王冰冰vlog弹幕并制作词云(https://mp.weixin.qq.com/
我的python总结
建议刚开始学习直接使用ANACONDAhttps://www.anaconda.com/download/配置python环境变量https://docs.python.org/3.6/using/cmdline.htmlenvvarPYTHONMALLOCPython PEP8导包顺序1. Python标准
商业数据分析从入门到入职(9)Python网络数据获取
@toc 前言本文主要讲Python最常见的应用之一——网络数据获取,即爬虫:先介绍了网页和网络的基础知识,为从网页中获取数据打好基础;接下来以两个案例介绍从网络中获取数据和处理数据的不同方式,以进一步认识Python爬虫和数据处理。 一、网络和网页基础知识 1.数据来源数据源有很多,可以从数据库中获取,可以从文件中获取,也可以从
一个没法商用,但是好玩有趣的 Python 手绘图形库!
https://github.com/chenjiandongx/cutecharts今天,给大家介绍一个很酷的 Python 手绘风格可视化神包:cutecharts。和 Matplotlib 、pyecharts 等常见的图表不同,使用这个包可以生成下面这种看起来像手绘的各种图表,在一些场景下使用效果可能会更好。GitHub 地址:https://git
天猫双11数据过于完美?我们用python来看看
↑关注+置顶 有趣的不像个技术号 是否真的完美? 双11结束了,大家已经无手可剁 。 天猫官方公布了今年的双11成交额为2684亿元,成功刷新了自己创下的商业纪录。按理说大家已经习惯了逐年增长,没想到 由于过于完美,引发网友提出质疑。 滑动图片浏览 or 点击查看大图▼ 该微博在天猫公布2019年销售额后,引发大量讨论,成功登上热搜。 一
一篇长文带你在python里玩转Json数据
↑一个宝藏公众号,长的好看的人都关注了 Json简介 Json(JavaScript Object Notation) 很多网站都会用到Json格式来进行数据的传输和交换,就像上篇我提到的,它们返回的数据都是Json格式的。这因为Json是一种轻量级的数据交换格式,具有数据格式简单,读写方便易懂等很多优点。用它来进行前后端的数据传输,大
https://cloud.tencent.com/developer/article/write/1830331
一、目标今天的目标是这个sign和appcode 二、步骤 Jadx没法上了app加了某梆的企业版,Jadx表示无能为力了。 FRIDADEXDumpDexDump出来,木有找到有效的信息。 Wallbreaker葫芦娃的Wallbreaker可以做些带壳分析,不过这个样本,用Frida的Spawn模式可以载入,Attach模式会失败。而直接用Objecti
什么,3行Python代码就能获取海量数据?
本文转载自公众号【法纳斯特】,详情可以点击上方卡片,关注该公众号,获取更多好文推荐。 一谈起数据分析,首先想到的就是数据,没有数据,谈何分析。 毕竟好的菜肴,没有好的原材料,是很难做的~ 所以本期小F就给大家分享一个获取数据的方法,只需三行代码就能搞定。 「GoPUP」,大佬造的轮子,大概有100+的免费数据接口。 GitHub:htt
干货|利用Python自动根据数据生成降雨量统计分析报告
作者:小小明 简介:Pandas数据处理专家,10余年编码经验,至今已帮助过成千上万名数据从业者解决工作实际遇到的问题,其中数据处理和办公自动化问题涉及的行业包括会计、HR、气象、金融等等,现为菜J学Python核心技术团队成员之一。 点击上方“Python爬虫与数据挖掘”,进行关注回复“书籍”即可获赠Python从入门到进阶共10本电子书今日鸡汤今夜偏
10行Python代码自动清理电脑内重复文件,解放双手!
](https://mp.weixin.qq.com/mp/appmsgalbum?actiongetalbum&albumid1337012041701326848&bizMzI1MTUyMjc1Mgwechatredirect) 前言 大家好,又到了Python办公自动化系列。今天分享一个系统层面的自动化案例:「给定一个文件夹,使用Python检查
手把手教你用Python操纵Word自动编写离职报告
前言大家好,我是吴老板,今天给大家分享一篇Python自动化文章。 Python 是自动化处理的一把好手,比如自动编写离职申请!!! 安装 pip install pythondocx i https://pypi.douban.com/simple/ 基本用法 创建一个docx文档from docx import Documentfrom docx.