使用 Stata 爬取冬奥会奖牌榜数据并绘图展示

上次的推文:如何使用 Stata 绘制一幅彩色的照片?给你的图表添加一个冰墩墩! 中我们爬取了冬奥会奖牌榜数据并绘图展示,但是那篇推文中并没有对数据爬取代码进行详细的讲解,今天我们就专门来学习下这个奖牌榜数据的爬起和绘图展示。

将冬奥会奖牌榜数据可以从这里看到:

https://tiyu.baidu.com/beijing2022/home/tab/%E5%A5%96%E7%89%8C%E6%A6%9C/from/pc

查看网页源代码可以看到网页上的数据就在源代码里面:

对着网页的空白处按鼠标右键选择显示网页源代码
很容易发现我们需要的数据就在这里

所以这是个静态网页,我们可以使用 copy 命令把这个网页下载下来:

clear
copy "https://tiyu.baidu.com/beijing2022/home/tab/%E5%A5%96%E7%89%8C%E6%A6%9C/from/pc" temp.html, replace

使用 infix 命令可以把这个文件读进 Stata 中:

infix strL v 1-10000 using temp.html, clear

strL v 1-10000 表示把 temp.html 文件每一行的 1-1000 个字符读进变量 v 中,变量 v 的类型是 strL (长字符串)。

分析源代码我们可以看到我们需要的数据所在行都有个 national-box:

图表

所以我们仅仅保留含有 national-box 的行:

keep if index(v, "national-box")

发现变量 v 里面存在空格,会影响下一步的处理,所以先把空格删去:

replace v = subinstr(v, " ", "", .)
图表

为了我们需要的数据从变量 v 中分离出来,我们可以先选择合适的切分符号对变量 v 进行切分,“><” 就非常合适:

split v, parse("><")
图表

检查可以发现我们需要奖牌数据在下面这几个变量中:

keep v6 v9 v10 v11 v12

并且所需的数据还都在 > 和 < 中间,所以可以对所有的变量应用正则表达式提取数据:

foreach i of varlist _all {
replace `i' = ustrregexs(1) if ustrregexm(`i', ">(.*)<")
}

compress
destring _all, replace

再重命名下变量就可以了:

ren v6 国家
ren v9 金牌
ren v10 银牌
ren v11 铜牌
ren v12 总计
save data, replace
图表

这样我们就爬取好了这份数据,下面我们选择前十个国家进行绘图展示:

use data, clear
keep in 1/10
sencode 国家, gsort(-金牌) replace

sencode 命令需要使用 ssc install sencode 安装,可以生成有序因子变量。

为了使用 twoway 绘制堆叠柱状图,我们需要对数据进行叠加:

* 绘制堆叠柱状图
replace 银牌 = 银牌 + 铜牌
replace 金牌 = 银牌 + 金牌

tw ///
bar 铜牌 国家, barwidth(0.7) color("239 199 16") || ///
rbar 银牌 铜牌 国家, barwidth(0.7) color("190 190 190") || ///
rbar 金牌 银牌 国家, barwidth(0.7) color("222 174 121") ///
xla(1(1)10, value ang(45)) xti("") yti("奖牌数") ///
leg(row(1) pos(11) ring(0) order(1 "金牌" 2 "银牌" 3 "铜牌")) ///
yla(0(5)45) ///
ti("2022 年北京冬奥会获得金牌前十名的代表团奖牌数") ///
subti("绘制:微信公众号 RStata") ///
caption("数据来源:百度体育" "<https://tiyu.baidu.com/beijing2022/home/tab/%E5%A5%96%E7%89%8C%E6%A6%9C/from/pc>")
图表

如果想把柱体按照高矮顺序排列,我们需要根据奖牌总数进行 sencode:

use data, clear
keep in 1/10
sencode 国家, gsort(-总计) replace

* 绘制堆叠柱状图
replace 银牌 = 银牌 + 铜牌
replace 金牌 = 银牌 + 金牌

tw ///
bar 铜牌 国家, barwidth(0.7) color("239 199 16") || ///
rbar 银牌 铜牌 国家, barwidth(0.7) color("190 190 190") || ///
rbar 金牌 银牌 国家, barwidth(0.7) color("222 174 121") ///
xla(1(1)10, value ang(45)) xti("") yti("奖牌数") ///
leg(row(1) pos(11) ring(0) order(1 "金牌" 2 "银牌" 3 "铜牌")) ///
yla(0(5)45) ///
ti("2022 年北京冬奥会获得金牌前十名的代表团奖牌数") ///
subti("绘制:微信公众号 RStata") ///
caption("数据来源:百度体育" "<https://tiyu.baidu.com/beijing2022/home/tab/%E5%A5%96%E7%89%8C%E6%A6%9C/from/pc>")
图表

点击这里跳转到 RStata 短书平台获取附件:使用 Stata 爬取冬奥会奖牌榜数据并绘图展示

评论