Expatistan 生活成本数据可视化 —— Stata 版本

Expatistan 生活成本数据可视化 —— Stata 版本

Stata 也是可以爬数据和绘制地图的,虽然没有 R 里面的那么容易,但是熟悉了之后也非常方便,本文就介绍了如何使用 Stata 完成上周的 Project。

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

  1. 数据源:Expatistan

  2. 世界地图数据:worldcoord.dta 和 worlddb.dta 数据。


Stata 版本参考答案

Stata 也是可以爬数据和绘制地图的,虽然没有 R 里面的那么容易,但是熟悉了之后也非常方便,本文就介绍了如何使用 Stata 完成上周的 Project。

再重复一遍,要爬的这个网址为:https://www.expatistan.com/cost-of-living/country/ranking

首先我们点击右键选择查看网页源代码:

然后找一下我们需要的这个表格的数据在哪,经过查找,可以发现这个表格的源代码是在 217——820 行,另外 859——958 行的 JavaScript 代码部分也有类似的数据,不过这个数据其实是那个交互式地图的数据。下面是爬取代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
clear all
/* 设置工作目录 */
cd worldshp
/* 把网址保存为一个名为 url 的 local 变量 */
local url = "https://www.expatistan.com/cost-of-living/country/ranking"
/* 把该网页的源代码拷贝下来保存为名为 expatistan.txt 的 txt 文件 */
copy `url' expatistan.txt, replace
/* 把这个 txt 文件读取到 Stata 中: */
infix strL v 1-20000 using expatistan.txt, clear
/*
通过源码的分析,发现我们想要的数据有两个地方有,第一部分是HTML代码里面的,
含有这两种字符:"<td>", "<td class="
例如:
<tr class="even " id="CH">
<td>4th</td>
<td class="country-name"><a href="https://www.expatistan.com/cost-of-living/country/switzerland">Switzerland</a></td>
<td>227</td>
</tr>
第二种是 JavaScript 代码里面的,其实这个数据是绘制页面上的那个地图的,我们先爬取
第一部分,我们只保存含有 "<td>" 和 "<td class=" 的行:
*/
keep if index(v, "<td>") | index(v, "<td class=")
/* 下面用正则表达式去除 HTML 标签 */
gen v2 = ustrregexs(1) if ustrregexm(v, ">(.*)<")
replace v2 = ustrregexs(1) if ustrregexm(v2, ">(.*)<")
/* 删除 v 变量 */
drop v
format v2 %20s
/* 注意其实只有前 297 行代码是我们想爬的那个表格上的数据 */
drop if _n > 297

/* 接下来就是把这个变量变成二维表格的形式了 */
postfile mypost str10 ranking str50 country ///
str10 price_index using price_index.dta, replace
forval i = 1(3)`=_N'{
post mypost (v2[`i']) (v[`i' + 1]) (v[`i' + 2])
}
postclose mypost

use price_index, clear
/* 压缩一下数据集 */
compress
/* 删除掉 price_index 中匹配到英文的观测值*/
drop if ustrregexm(price_index, "[a-z]")
destring _all, replace
save ranking, replace

爬取后得到的数据是这样的:

然后是绘制地图:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
use worlddb.dta, clear
ren name country
replace country = "United States of America" if country == "United States"
merge 1:1 country using ranking
* spmap 可以这样装:
* net install spmap.pkg, from("https://czxa.top/pkg/spmap") replace
spmap price_index using worldcoord, id(ID) fcolor(Reds) ///
clnumber(5) ocolor("black" ...) ///
ti("各国生活成本指数", size(*1.2) color(black)) ///
graphr(margin(medium)) ///
subti("Czech Republic = 100") ///
osize(vthin ...) ///
legend(size(*1.5) ///
order(2 "182~334" 3 "130~182" 4 "100~130" 5 "87~100" 6 "66~87") ///
ti(确诊, size(*0.5) pos(11) color(black)) color(black)) ///
xsize(20) ysize(10) ///
caption("数据来源:Expatistan | 绘制:TidyFriday", size(*0.8) color(black))
gr export price_index.png, replace

最后我们再试试从 JavaScript 那部分提取数据,比较简单:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
/*
再回到数据爬取的部分,刚刚我们是从 HTML 文件中提取了数据,
现在我们再从 JavaScript 中提取数据
*/
infix strL v 1-20000 using expatistan.txt, clear
keep if index(v, "],")
split v, parse(,)
drop v
replace v1 = subinstr(v1, "[", "", .)
replace v1 = subinstr(v1, `"""', "", .)
replace v2 = subinstr(v2, "]", "", .)
drop in 1
drop in -1
keep v1 v2
ren v1 country
ren v2 price_index
save price_index, replace

地图我就不再画第二遍了。。。

知识星球附件链接:https://t.zsxq.com/YvjaE2V

#

评论

Your browser is out-of-date!

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

×