Python版:Expatistan生活成本数据可视化

Python版:Expatistan生活成本数据可视化

Expatistan 生活成本数据分析是我们社区去年 12 月 15 号的时候布置的一个 Project,今天我们再重新回顾一下这个 Project,改进一下图表绘制部分。

Project 题目

我的 Project 题目一般使用 R 语言布置:

本周的小项目作业是“爬取 Expatistan 网站上的各国生活成本数据并绘制一幅世界地图进行展示”。

  1. 数据源:Expatistan

  2. 世界地图的底图数据:tmap 包内有一个 World 数据,调用方法:

1
data("World", package = "tmap")
  1. 爬取数据的 R 包,可以用 rvest

Tips: 可能需要到的函数:read_html,html_nodes,html_table;

  1. 绘制地图的 R 包,ggplot + sf (本周有教程),用 tmap 也行。

  2. 拓展作业:可以再绘制一些其他的图来展示各国生活成本的排名。

Python 版本参考答案

Python 爬取 Expatistan 网站上的各国生活成本指数数据也非常简单,只要根据 XPath 找到表格对应的 HTML 代码,然后调用 pandas 包的 read_html() 函数把 HTML 格式的表格读取为数据框即可。

数据爬取

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
import requests
from lxml import etree
r = requests.get('https://www.expatistan.com/cost-of-living/country/ranking')
dom_tree = etree.HTML(r.content)
table = dom_tree.xpath('//*[@id="content"]/div/div[1]/div[1]/table')
table = etree.tostring(table[0], encoding = 'utf-8').decode()
import pandas as pd
df = pd.read_html(table, encoding = 'utf-8', header = 0)[0]
df

#> Ranking Country Price Index *
#> 0 1st Cayman Islands 280
#> 1 2nd Hong Kong 226
#> 2 3rd Switzerland 223
#> 3 4th Iceland 218
#> 4 5th Bahamas 214
#> .. ... ... ...
#> 91 92nd Tanzania 70
#> 92 93rd Georgia 70
#> 93 94th Paraguay 67
#> 94 95th Tunisia 64
#> 95 96th India 64
#> [96 rows x 3 columns]

地图绘制准备

接下来就是绘制地图了。首先导入需要的库:

1
2
3
4
5
6
7
8
import geopandas as gpd
import matplotlib.pyplot as plt
from matplotlib import rcParams
from matplotlib.font_manager import FontProperties
# 查看 Matplotlib 中可用的字体
import matplotlib
a = sorted([f.name for f in matplotlib.font_manager.fontManager.ttflist])
a

我们从中选择 Songti SC,也就是宋体,然后修改字体域、图表的分辨率和保存图片的分辨率:

1
2
3
plt.rcParams['font.family'] = ['Songti SC']
rcParams['figure.dpi'] = 300
rcParams['savefig.dpi'] = 300

读取地图文件

这里我更换了地图数据文件,这里使用的是带有九段线的世界地图数据:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
worldshp = "worldshp/world.shp"
map_df = gpd.read_file(worldshp)
map_df.head()

#> id name geometry
#> 0 AFG Afghanistan POLYGON ((61.21082 35.65007, 62.23065 35.27066...
#> 1 AGO Angola MULTIPOLYGON (((16.32653 -5.87747, 16.57318 -6...
#> 2 ALB Albania POLYGON ((20.59025 41.85540, 20.46317 41.51509...
#> 3 ARE United Arab Emirates POLYGON ((51.57952 24.24550, 51.75744 24.29407...
#> 4 ARG Argentina MULTIPOLYGON (((-65.50000 -55.20000, -66.45000...

# 开启交互模式
plt.ion()
# 绘图
map_df.plot()

下面合并地图数据集和我们爬取到的各国生活成本指数数据,然后绘制地图:

1
merged = map_df.set_index('name').join(df.set_index('Country'))

隐藏警告:

1
2
import warnings
warnings.filterwarnings("ignore")

然后就可以绘制世界地图了:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
import matplotlib.patches as mpatches
fig, ax = plt.subplots(1, figsize = (10, 6))
# 移除坐标轴
ax.axis('off')
# 添加标题
ax.set_title('Expatistan生活成本指数数据可视化',
fontdict = {'fontsize': '25', 'fontweight': '3'})
# 添加注释
ax.annotate('数据来源:Expatistan', xy = (0.1, 0.08),
xycoords = 'figure fraction',
horizontalalignment = 'left',
verticalalignment = 'top',
fontsize = 12, color = '#555555')
# 创建图例
pd.qcut(df["Price Index *"], 4)
legend_element = [mpatches.Patch(facecolor = "#edf8fb", label = "64 ~ 85"),
mpatches.Patch(facecolor = "#b2e2e2", label = "85 ~ 105"),
mpatches.Patch(facecolor = "#66c2a4", label = "105 ~ 153"),
mpatches.Patch(facecolor = "#238b45", label = "153 ~ 280"),]
plt.legend(handles = legend_element, loc = "lower left", title = "Price Index")
merged.plot(column = 'Price Index *', cmap = 'Greens',
linewidth = 0.2, ax = ax,
edgecolor = 'gray')
plt.savefig("Price.png")

# Python

评论

Your browser is out-of-date!

Update your browser to view this website correctly. Update my browser now

×