13.3.3 获取各项指标

13.3.3 获取各项指标



若要获取有关国家或地区的数据,需要使用世界银行服务的不同函数。函数的路径是 /countries/indicators(/国家/指标),可以在 Data Calls 选项卡下的 Query Generator(查询生成器)中找到。能够请求指定国家特定时间段内的有关指标数据。不是单独下载我们感兴趣的数据每个区域,而是一次获取所有国家的信息,并在内存中处理。虽然以这种方式会下载更多的数据,但是,使用数量较少的请求,因为我们根本不必为每个区域创建请求。

我们将按照与以前相同的模式,首先下载部分示例数据,然后,使用我们的 XML 查询函数来检查。清单 13.11 显示了如何下载一个国家的森林覆盖率指标,这项指标的键是 AG.LND.FRST.ZS,最好办法是在查询生成器中模拟查询。我们将下载 1990 年的数据,并请求数据集的第一页。



Listing 13.11 Obtaining area covered by forests (F# Interactive)



> let ind = "AG.LND.FRST.ZS"
let date = "1990:1990"
let page = 1
let props =
[ "countries", "indicators"; ind ]
[ "date", date; "page", string(page) ];;
(...)

> let doc = Async.RunSynchronously(worldBankRequest(props))
printfn "%s..." (doc.ToString().Substring(0, 301));;
val doc : XDocument
<wb:data xmlns:wb="http://www.worldbank.org"
page="1" pages="3" per_page="100" total="231">
<wb:data>
<wb:indicator id="AG.LND.FRST.ZS">Forest area (% ...</wb:indicator>
<wb:country id="AW">Aruba</wb:country>
<wb:value></wb:value>
<wb:date>1990</wb:date>
</wb:data>...

> doc |> xnested [ "data" ]
|> xattr "pages" |> int;;
val it : int = 3

> doc |> xnested [ "data"; "data"; "country" ]
|> xvalue;;
val it : string = "Aruba"



清单 13.11 首先定义了一组为了创建请求而指定的属性。然后,创建一个用于 worldBankRequest 函数的属性列表。下载文档之后,想要探索其结构,所以,要把它转换成字符串,打印出前几行。输出表明,整个数据集有三个页。每个国家的信息被嵌套在 data 元素中,包含国家名和 ID,有关数据的信息,和实际值。对于第一个国家,这个值省略了,所以,在解析数据时,我们必须小心处理这种情况。

接下来,写了两个简单表达式,我们很快就会需要。首先,我们需要读出页数,这样,我们就能下载所有数据。第二个表达式读出第一个国家名,在后面会需要,因为,希望它与我们在上一节中收集的区域的名字相匹配。

现在,对于这些数据的结构,我们有一个很好的概念,就可以写函数,来下载我们所需的一切。清单 13.12 显示了一个异步的工作流,循环运行,直至获得所有页。我们没有并行下载页面,因为,这会稍微难写,但是,对于不同指标和不同年份,我们将并行运行相同的函数,这样,最终也会有足够的并行度。



Listing 13.12 Downloading all indicator data asynchronously (F#)



let rec getIndicatorData(date, indicator, page) = async {
let args = [ "countries"; "indicators"; ind ],
[ "date", date; "page", string(page)]
let! doc = worldBankRequest args

let pages =
doc |> xnested [ "data" ]
|> xattr "pages" |> int
if (pages = page) then
return [doc]
else
let page = page + 1
let! rest = getIndicatorData(date, indicator, page)
return doc::rest }



这个函数取日期、指标以及所需的页数作为参数,用它们来生成 worldBankRequest 函数参数值列表。当收到 XML 时,读出数据集总页数的属性。如果当前正在处理的页是最后一个,我们就会返回只有一个元素的列表,包含在当前页。否则,我们需要下载其余页。注意,该函数用 let rec 声明,所以,我们可以递归地调用它,获得剩余页。还使用了 let!,因为是在异步工作流的内部。一旦得到了其余页的列表,再加上刚刚下载的页,就可以返回所有页作为结果。

在继续之前,可以使用 F# Interactive 来验证函数的正确性。制作一个要求,指标为 AG.LND.FRST.ZS,年度范围 1990:1990,页数为 1。当使用 Async.RunSynchronously,运行该工作流,应该得到三页,包含有关所有国家和地区的数据。

现在,让我们介绍一下并行度,下载我们感兴趣年度的所有指标。我们将使用 Async.Parallel 基元,因此,需要创建异步工作流的序列。清单 13.13 中的代码通过使用简单的序列表达式,调用 getIndicatorData 函数,实现所有参数的组合来实现。别忘了,调用 getIndicatorData 不执行读取,它返回可以执行读取的工作流。



Listing 13.13 Downloading multiple indicators for multiple years in parallel (F#)



let downloadAll = seq {
for ind in [ "AG.SRF.TOTL.K2"; "AG.LND.FRST.ZS" ] do
for year in [ "1990:1990"; "2000:2000"; "2005:2005" ] do
yield getIndicatorData(year, ind, 1) }

let data = Async.RunSynchronously(Async.Parallel(downloadAll))



脚本首先为我们感兴趣的指标和年度的每个组合,生成工作流,然后,它将所有工作流组合为平行运行的一个,并同步运行,来下载所有数据。

序列表达式首先迭代两个指标。第一个表示国家或地区总面积,以平方公里计,第二个是森林覆盖的百分比,正如我们已经看到的。如果在世界银行的网站上看数据的话,可以看到,森林覆盖指标只供三个不同年份,因此,嵌套的循环只遍历这些年份。对于这些参数的每个组合,我们创建 (产生)一个工作流,第一页开始运行下载。

这意味着,我们就会得到总共六个任务,其中每一个都可能下载多个页面。我们将这些任务组合到一个工作流,返回这六个结果的一个数组,使用 Async.RunSynchronously 运行组合的工作流。下载可能花一些时间,可能看到一些请求会失败,然后重新启动,正如我们前面讨论的。我们得到的 data 值的类型,结果是 array<list<XDocument>>。这个数组包含了页面列表,返回了每个指标-年组合。

因为我们正在写一个 F# 脚本,不必担心读写配置文件,比如年和指标。此刻,我们写的代码只有一个目的。我们以后可以修改它,使它更通用,但是,可以在后来的开发中碰到。现在,我们已经检索了所需要的数据,用它来一些有用的事情。


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值