119 11 个案例掌握 Python 数据可视化--二手房市场研究

二手房市场研究

房产是大多数年轻人考虑扎根、有经济实力的人考虑置业的重要资产类型之一,本实验获取了爬虫收集的房天下官网的一个样例二手房数据集,通过对该数据集的分析,可视化了样本中各省建筑面积、价格、小区绿化率等数据。

数据集准备

本数据来自数据超市的一个样例数据,共 1679 条房产信息,主要包括省份,城市,区县,小区类型,经纬度等字段。
导入数据并查看前 5 行。

import pandas as pd
df=pd.read_excel('https://labfile.oss.aliyuncs.com/courses/3023/Second_hand_house.xls')
df.head()

全国各省二手房建筑面积

进行地图的可视化主要是通过 Pyecharts 包实现,Pyecharts 主要由两个类进行地图的可视化:
Map 类可视化的方式是将行政区块作为数据的映射对象,即行政区块整体面积的颜色与数值构成映射关系;
Geo 类可视化的方式是将经纬度坐标作为数据的映射对象,相比 Map 而言, Geo 相对灵活,可以传入不同的绘图对象。

Map 对象传入的数据类型为二维列表,列表各元素为 [名称,数据]。需要注意的是,名称须与 maptype 层级对应。例如: maptype 默认层级是 china ,则名称层级应为省(或者省会、直辖市)一级,若将 maptype 设置为广东,则名称的层级应该为市一级,比如中山市。
数据准备

data=df
data=data.groupby(['省份'])['建筑面积'].sum().sort_values(ascending=False)
data_pair=[ [province,area] for province,area in zip(data.index,data)]
data_pair[:5]

绘图

!pip install pyecharts==1.7.1

将各省总建筑面积进行聚合,在.add() 接口传入 data_pair 参数即可完成各省总建筑面积分布图的绘制。

from pyecharts import options as opts
from pyecharts.charts import Map
import matplotlib.colors as cs


data = df
data = data.groupby(['省份'])['建筑面积'].sum().sort_values(ascending=False)

data_pair = [[province, area] for province, area in zip(data.index, data)]

m = Map()
m.add(
    series_name="",
    data_pair=data_pair,
    maptype='china',
    label_opts=opts.LabelOpts(is_show=False),
    is_map_symbol_show=False,
)
m.set_global_opts(
    title_opts=opts.TitleOpts(
        title="中国各省二手房总建筑面积分布图",
        subtitle="数据来源:房天下 单位:平方米",
        pos_left="center",
        pos_top="top",
        title_textstyle_opts=opts.TextStyleOpts(
            font_size=25
        ),
    ),
    # 颜色设置
    visualmap_opts=opts.VisualMapOpts(
        is_calculable=True,
        pos_left="10", # 颜色条与左侧间距
        min_=100000, # 颜色条映射数值最小值
        max_=10000000,# 颜色条映射数值最大值
        range_text=["High", "Low"], # 颜色条两端文字
        range_color=[cs.TABLEAU_COLORS['tab:blue'],   # 颜色渐变范围最小值为蓝色,依次为橘色,最大值为红色
                     cs.TABLEAU_COLORS['tab:orange'],
                     cs.TABLEAU_COLORS['tab:red']],
        textstyle_opts=opts.TextStyleOpts(color="black"),
    ),
)
m.render_notebook()

输出的地图支持交互性,体现在:
鼠标悬停在任一省份面积块,会弹出该块面积对应省份的总建筑面积数值大小;
颜色条上方和下方的三角形按钮支持鼠标拖拽,当数据拖拽按钮时,地图中对应数值的颜色块也将随之变动;
鼠标悬停在地图范围内时,通过滑动鼠标中间滚轮,可以缩放地图的大小;
鼠标点击任一省份位置不松开,可以移动整张地图位置。

从输出结果可以看出:样本数据中,最大的建筑面积省份为江苏省。

全国各省二手房建筑面积排序

上述数据可通过条形图进行各省相对数值的展示。

from pyecharts.charts import Bar

data = df
data = data.groupby(['省份'])['建筑面积'].sum().sort_values(ascending=False)

bar = Bar()
bar.add_xaxis(list(data.index))
bar.add_yaxis("总建筑面积", list(data), label_opts=opts.LabelOpts(is_show=False))
bar.set_global_opts(
    title_opts=opts.TitleOpts(title=" ", subtitle=" "),
    yaxis_opts=opts.AxisOpts(axislabel_opts=opts.LabelOpts(is_show=True)),
    xaxis_opts=opts.AxisOpts(axislabel_opts=opts.LabelOpts(rotate=45)),
    legend_opts=opts.LegendOpts(is_show=False),
    visualmap_opts=opts.VisualMapOpts(
        is_show=False,
        min_=100000,
        max_=10000000,
        range_text=["High", "Low"],
        range_color=[cs.TABLEAU_COLORS['tab:blue'],
                     cs.TABLEAU_COLORS['tab:orange'],
                     cs.TABLEAU_COLORS['tab:red']],
    ),
)
bar.render_notebook()

通过 Grid 类对象,将地图与条形图合并在一张图纸上。需要注意的时,如希望地图和条形图颜色做到一致对应,两者的 visualmap_opts 须做到最大值(max_)、最小值(min_)、颜色变化范围(range_color)等参数设置相同。

from pyecharts.charts import Grid
grid=Grid(init_opts=opts.InitOpts(width='800px',height='700px'))
grid.add(bar, grid_opts=opts.GridOpts(pos_top="60%"))
grid.add(m, grid_opts=opts.GridOpts(pos_bottom="50%"))
grid.render_notebook()

江苏省各城市建筑面积

对于总建筑面积最大的江苏省,可通过将 maptype 设置为江苏,可视化江苏省内各城市建筑面积。需要注意的是,原数据集各城市名称不带“市”,须将其补充完成。

data = df
data=data.loc[data['省份']=='江苏']
data = data.groupby(['城市'])['建筑面积'].sum().sort_values(ascending=False)

data_pair = [[city+"市", area] for city, area in zip(data.index, data)]

m = Map()
m.add(
    series_name="",
    data_pair=data_pair,
    maptype='江苏',
    label_opts=opts.LabelOpts(is_show=False),
    is_map_symbol_show=False,
)
m.set_global_opts(
    title_opts=opts.TitleOpts(
        title="江苏省二手房总建筑面积分布图",
        subtitle="数据来源:房天下 单位:平方米",
        pos_left="center",
        pos_top="top",
        title_textstyle_opts=opts.TextStyleOpts(
            font_size=25
        ),
    ),
    # 颜色设置
    visualmap_opts=opts.VisualMapOpts(
        is_calculable=True,
        pos_left="10", 
        min_=1000, 
        max_=1550000,
        range_text=["High", "Low"], 
        range_color=[cs.TABLEAU_COLORS['tab:blue'],   
                     cs.TABLEAU_COLORS['tab:orange'],
                     cs.TABLEAU_COLORS['tab:red']],
        textstyle_opts=opts.TextStyleOpts(color="black"),
    ),
)
m.render_notebook()

全国各省二手房价格

将每个小区的价格映射到地图上,该问题无法通过 Map 类实现,原因是 Map 类是根据层级关系认识数据对名称的,比如,我们可以通过中国认识江苏,可以通过江苏认识南京市,但是无法通过中国或者江苏认识阳光小区。实现该问题需要通过 Geo 地图的 .add_coordinate 接口实现,其原理是:
先通过 .add_coordinate 接口将各个带经纬度的坐标注册至地图,并将经纬度与名称构成一一对应关系;
通过注册过的名称与数据的对应关系,完成相关类型图表的绘制。

本例将数据集中的小区经纬度注册至地图中,并将每个小区对应的房价以热力图的形式绘制到地图上。

from pyecharts.charts import Geo
from pyecharts.globals import ChartType

data = df[['小区名称', '经度', '纬度', '价格']].copy()
# 去除没有经纬度和价格的小区数据
data.dropna(how='any', inplace=True)

geo = Geo()

# 设置地图类型及是否可缩放
geo.add_schema(maptype="china", is_roam=True)

# 将每个小区添加到地图的坐标系中
for name, longitude, latitude in zip(data['小区名称'], data['经度'], data['纬度']):
    geo.add_coordinate(name=name, latitude=latitude, longitude=longitude)

# 将每个小区的价格添加到地图的数据对中
data_pair = [[name, price] for name, price in zip(data['小区名称'], data['价格'])]

# 添加数据
geo.add(
    "小区价格 元/平方米",
    data_pair,
    type_=ChartType.HEATMAP, # 热力图类型
    point_size=12, # 每个小区对应数据点的直径
)

# 进行系列设置
geo.set_series_opts(label_opts=opts.LabelOpts(is_show=False))

# 进行全局设置
geo.set_global_opts(visualmap_opts=opts.VisualMapOpts(
    is_calculable=False,
    dimension=0,
    pos_left="10",
    min_=1000,
    max_=70000,
    pos_top="center",
    range_text=["high", "low"],
    range_color=["green", "yellow", "red"],
),
    title_opts=opts.TitleOpts(title="各省二手房价格分布图"))

# 渲染并输出
geo.render_notebook()

输出的热力地图为密度合成图。在不同的地图尺度上,我们看到的色块是该尺度下各子元素的汇总结果。例如:
当尺度放在全国范围内时,会发现江浙沪地区均为红色(红色对应的价格为 70000 元/平方米);
当滑动鼠标滚轮,放大江浙沪地区至满屏时,会发现随着地图逐步放大,大块的红色慢慢消失,取而代之的是带状的红色和绿色块;
进一步放大,可看到一个个的圆圈点,该圆点表示该经纬度对应小区的均价;
同理,如果反方向操作,即将地图无限缩小,则会看到全国东南地区将收缩成一个大红色的圆。

从输出结果可以看出:全国二手房房价仍然以江浙沪、东南地区、北京首都为最高。

全国各省二手房绿化率

同样的方式将各小区的绿化率进行可视化。

data = df[['小区名称', '经度', '纬度', '绿化率']].copy()

data.dropna(how='any', inplace=True)

geo = Geo()

geo.add_schema(maptype="china", is_roam=True)

for name, longitude, latitude in zip(data['小区名称'], data['经度'], data['纬度']):
    geo.add_coordinate(name=name, latitude=latitude, longitude=longitude)


data_pair = [[name, green] for name, green in zip(data['小区名称'], data['绿化率'])]

geo.add(
    "小区绿化率 %",
    data_pair,
    type_=ChartType.HEATMAP,
    point_size=5,
)


geo.set_series_opts(label_opts=opts.LabelOpts(is_show=False))

geo.set_global_opts(visualmap_opts=opts.VisualMapOpts(
    is_calculable=True,
    dimension=0,
    pos_left="10",
    is_piecewise=True, # 将热力图颜色条设置为离散形式
    min_=0.1,
    max_=0.9,
    pos_top="center",
    range_text=["high", "low"],
    range_color=["red", "yellow", "green"],
    textstyle_opts=opts.TextStyleOpts(color="black"),
),
    title_opts=opts.TitleOpts(title="各省二手房小区绿化率分布图"))

# 渲染并输出
geo.render_notebook()

标注不同类型小区

除热力图外,Geo 对象也支持散点图,本例将不同类型的小区通过不同颜色的点映射到地图上。

import numpy as np
data = df[['小区名称', '类型', '经度', '纬度']].copy()
data.dropna(inplace=True)
data


geo = Geo()
geo.add_schema(maptype="china", is_roam=True)

# 注册各小区名称及经纬度
for name, longitude, latitude in zip(data['小区名称'], data['经度'], data['纬度']):
    geo.add_coordinate(name=name, latitude=latitude, longitude=longitude)

colors = [cs.TABLEAU_COLORS['tab:blue'],
          cs.TABLEAU_COLORS['tab:orange'],
          cs.TABLEAU_COLORS['tab:red'],
          cs.TABLEAU_COLORS['tab:green']]

# 将各种类型的小区以散点的形式添加到地图中
for i, building_type in enumerate(np.unique(data['类型'])):
    type_data = data.loc[data['类型'] == building_type]

    geo.add(
        building_type,
        [[name, 1] for name in type_data['小区名称']],
        type_=ChartType.SCATTER,
        symbol_size=6,
        color=colors[i]
    )


geo.set_series_opts(label_opts=opts.LabelOpts(is_show=False))
geo.set_global_opts(title_opts=opts.TitleOpts(title="各省二手房小区类型分布图"))
geo.render_notebook()

从输出结果可以看到,样本数据中数量最多的房产类型是住宅,占到了主要的比例,写字楼、商铺、别墅相对较少。

出差轨迹图

Geo 类同样支持折线图,以下通过虚拟案例绘制某人从上海出差,途径昆明, 乌鲁木齐, 郑州等地后返回上海的路线图。

from pyecharts.globals import SymbolType

lines = ['上海', '昆明', '乌鲁木齐', '郑州', ]

lines = [[start, stop] for start, stop in zip(
    np.array(lines), np.append(lines[1:], lines[0]))]


geo = Geo()
geo.add_schema(maptype="china", is_roam=True)


geo.add(
    '',
    lines,
    type_=ChartType.LINES,
    effect_opts=opts.EffectOpts(   # 设置线条动态效果
        symbol=SymbolType.ARROW,
        symbol_size=6,
        color=cs.TABLEAU_COLORS['tab:blue']
    ),
    linestyle_opts=opts.LineStyleOpts(
        curve=0.2,
        color=cs.TABLEAU_COLORS['tab:red']),
)


geo.set_series_opts(label_opts=opts.LabelOpts(is_show=False))
geo.set_global_opts(title_opts=opts.TitleOpts(title="出差路线图"))
geo.render_notebook()

根据建成年可视化二手房价格变化趋势

数据准备
带地图的可视化看板是近些年可视化领域的一个热点,本例实现了按建成年度可视化各省二手房的均价。

data = df.copy()

data = data[['价格', '省份', '建成年']]
# 去除带有空值的数据
data.dropna(inplace=True)
data['建成年'] = data['建成年'].apply(lambda x: int(x))

data.head()

绘图
按年度动态变化的可视化图制作原理如下:
生成一个 Timeline 类对象;
遍历每一年,并将需要可视化的对象通过 Grid 对象进行图纸拼接;
通过 Timeline 类对象的 .add() 接口进行 Grid 对象的添加。

from pyecharts.charts import Timeline

timeline = Timeline(
    init_opts=opts.InitOpts(
        width='800px',
        height='700px',
        theme='dark', # 设置主题为暗色
    )
)
timeline.add_schema(play_interval=900)  # 播放时间间隔,单位是 ms

for year in sorted(np.unique(data['建成年'])):

    year_data = data.loc[data['建成年'] == year]
    year_data = year_data.groupby(
        ['省份'])['价格'].mean().sort_values(ascending=False)

    data_pair = [[province, price]
                 for province, price in zip(year_data.index, year_data)]

    #-------------------地图-------------------------#
    m = Map()
    m.add(
        series_name="",
        data_pair=data_pair,
        label_opts=opts.LabelOpts(is_show=False),
        is_map_symbol_show=False,
    )
    m.set_global_opts(
        title_opts=opts.TitleOpts(
            title="各省二手房平均价格按建成年分布图",
            subtitle="数据来源:房天下 单位:元/平方米",
            pos_left="center",
            pos_top="top",
            title_textstyle_opts=opts.TextStyleOpts(
                font_size=25
            ),
        ),
        visualmap_opts=opts.VisualMapOpts(
            is_calculable=True,
            dimension=0,
            pos_left="10",
            min_=year_data.min(),
            max_=year_data.max(),
            pos_top="center",
            range_text=["High", "Low"],
            range_color=[cs.TABLEAU_COLORS['tab:blue'],
                         cs.TABLEAU_COLORS['tab:orange'],
                         cs.TABLEAU_COLORS['tab:red']],
            textstyle_opts=opts.TextStyleOpts(color="#ddd"),
        ),
    )
    #-------------------条形图-------------------------#
    bar = Bar()
    bar.add_xaxis(list(year_data.index))
    bar.add_yaxis("总建筑面积", list(year_data), label_opts=opts.LabelOpts(is_show=False))
    bar.set_global_opts(
        title_opts=opts.TitleOpts(title=" ", subtitle=" "),
        yaxis_opts=opts.AxisOpts(axislabel_opts=opts.LabelOpts(is_show=True)),
        xaxis_opts=opts.AxisOpts(axislabel_opts=opts.LabelOpts(rotate=45)),
        legend_opts=opts.LegendOpts(is_show=False),
        visualmap_opts=opts.VisualMapOpts(
            is_show=False,
            min_=year_data.min(),
            max_=year_data.max(),
            range_text=["High", "Low"],
            range_color=[cs.TABLEAU_COLORS['tab:blue'],
                         cs.TABLEAU_COLORS['tab:orange'],
                         cs.TABLEAU_COLORS['tab:red']],
        ),
    )
    
    #-------------------合并-------------------------#
    grid=Grid()
    grid.add(bar, grid_opts=opts.GridOpts(pos_top="65%",pos_bottom="10%"))
    grid.add(m, grid_opts=opts.GridOpts(pos_bottom="50%"))
    
    #-------------------添加到时间线-------------------------#
    timeline.add(grid, "{}年".format(year))
timeline.render_notebook()

点击输出结果图下方的三角形按钮,图将自动按年播放历年数据情况。静态环境下,也可以通过点击每个年度节点,展示该年度的数据。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,324评论 5 476
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,303评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,192评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,555评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,569评论 5 365
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,566评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,927评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,583评论 0 257
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,827评论 1 297
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,590评论 2 320
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,669评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,365评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,941评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,928评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,159评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,880评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,399评论 2 342