二手房市场研究
房产是大多数年轻人考虑扎根、有经济实力的人考虑置业的重要资产类型之一,本实验获取了爬虫收集的房天下官网的一个样例二手房数据集,通过对该数据集的分析,可视化了样本中各省建筑面积、价格、小区绿化率等数据。
数据集准备
本数据来自数据超市的一个样例数据,共 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()
点击输出结果图下方的三角形按钮,图将自动按年播放历年数据情况。静态环境下,也可以通过点击每个年度节点,展示该年度的数据。