13.3.3 获取指标

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

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

清单 13.11 获得地区的森林覆盖率 (F# Interactive)

> let ind = "AG.LND.FRST.ZS"  | 指定 1990 年地区
   let date = "1990:1990"     | 森林数据的第一页
   let page = 1              |
   let props =
     [ "countries", "indicators"; ind ]
     [ "date", date; "page", string(page) ];;
(...)

> let doc = Async.RunSynchronously(worldBankRequest(props))  | [1] 获得数据,
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" ]  | 读第一个国家的 ID
     |> xvalue;;                           |
val it : string = "Aruba"

清单 13.11 首先定义了一组属性,这是为了创建请求而需要的;然后,创建一个属性的列表,这是 worldBankRequest 函数所需要的。下载文档之后,我们要浏览一下结构,因此,要把它转回字符串,输出前面几行[1]。输出的结果表明,整个数据集有三页;每个国家的信息嵌套在 data 元素中,包含国家的名字和 ID,以及日期(感觉应该是 date)信息和实际值。第一个国家没有这个值,所以,在解析数据时,我们必须要小心处理这种情况。

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

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

清单13.12 异步下载所有指标 (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" ]    | [1] 得到页数
          |> xattr "pages" |> int   |
  if (pages = page) then
    return [doc]    <-- [2] 返回最后的页面
  else
    let page = page + 1
    let! rest = getIndicatorData(date, indicator, page)  <-- [3] 下载其余的页面
    return doc::rest }

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

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

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

清单13.13 并行下载多年的多指标 (F#)

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

let data = Async.RunSynchronously(Async.Parallel(downloadAll))    [2]

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

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

这就是说,我们会得到总共六个任务,其中每一个都可能下载多个页面;我们将这些任务组合成一个工作流,返回一个包含这六个结果的数组,使用 Async.RunSynchronously 运行组合的工作流。下载要会花一些时间,某些请求可能会失败,然后重新启动,正如我们前面讨论的。我们得到的结果 data 值,类型是 array

时间: 2024-08-10 19:15:42

13.3.3 获取指标的相关文章

13、java获取路径

1.获取WEB-INF文件夹下的文件 /C:/Users/Administrator/Workspaces/MyEclipse%2010/day_38_spring_hibernate/WebRoot/WEB-INF/classes/com/itheima/test/ 1 String path=TestHibernate.class.getResource("").getPath(); 2 System.out.println(path); 其对应的文件位置是 2.获取WEB-INF

java学习第13天( java获取当前时间,有关大数据的运算及精确数字运算,Date类)

一 java获取当前时间 学习一个函数,得到当前时间的准确值 System.currectTimeMillis(). 可以得到以毫秒为单位的当前时间.它主要用于计算程序运行时间,long start=System.currectTimeMillis() ,long stop=System.currectTimeMillis() , stop-start; 二  有关大数据的运算及精确数字运算. 此时integer不适用.我们使用BigInteger ,如:BigInteger B= new Bi

(13)-Python3之--获取当前时间

1.导入datetime模块 import datetime 2.获取当前日期和时间 import datetime now_time = datetime.datetime.now() print(now_time) 结果: 2020-03-23 15:28:51.143440 3.转换成我们想要的日期,去除时间 import datetime now_time=datetime.datetime.now().strftime('%Y-%m-%d') print(now_time) 结果: 2

js中获取时间new date()的用法

js中获取时间new date()的用法 获取时间:   var myDate = new Date();//获取系统当前时间 获取特定格式的时间: 1 myDate.getYear(); //获取当前年份(2位) 2 myDate.getFullYear(); //获取完整的年份(4位,1970-????) 3 myDate.getMonth(); //获取当前月份(0-11,0代表1月) 4 myDate.getDate(); //获取当前日(1-31) 5 myDate.getDay();

java通过反射获取调用变量以及方法

一:反射概念 可以通过Class类获取某个类的成员变量以及方法,并且调用之. 二:通过反射获取方法.变量.构造方法 1 @Test 2 // 通过反射获取类定义的方法 3 public void testMethod() throws Exception { 4 @SuppressWarnings("rawtypes") 5 Class clazz = Class.forName("java.lang.String"); 6 Method[] m = clazz.g

第13章 Linux的网络管理

本文目录: 13.1 Linux数据包转发功能 13.2 和网络相关的几个文件说明 13.2.1 网卡配置文件ifcfg-* 13.2.2 DNS配置文件/etc/resolve.conf 13.2.3 /etc/udev/rules.d/70-persistent-net.rules 13.2.4 /etc/services 13.3 网络接口配置和主机名 13.3.1 ifconfig 13.3.2 ifcfg 13.3.3 hostname命令 13.4 网关/路由 13.4.1 rout

JS获取文本节点

1 <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd"> 2 <html> 3 <head> 4 <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> 5 <titl

获取本机CPU,硬盘等使用情况

早上的时候接到主管的一个任务,要获取服务器上的cpu,硬盘, 数据库等 的使用情况,并以邮件的方式发给boss, = =没办法,公司的服务器真是不敢恭维,顺便吐槽一下公司的网速,卡的时候30k左右徘徊,这不是在浪费我们的时间吗!!! 话不多说上代码,因为是实习,主管还是挺关照我的,一早就给我发了个类库(里面涉及到要查询本机信息的都有).这样我剩下了一大半的时间, 这个功能总的来说就两步:  一,先获取本机的信息    二,发送邮件. 获取本机信息用到的类库 SystemInfo.cs 和 Dis

MFC中App,Doc,MainFrame,View各指针的互相获取

首先说明这四个类的 执行顺序是:App->Doc->MainFrame->View 消息响应顺序是:View->Doc->MainFrame->App 1 // App中获取其它三项指针 2 void CSDIApp::OnApp() 3 { 4 // App 5 // Doc 6 CDocument *pDoc = ((CFrameWndEx *)m_pMainWnd)->GetActiveDocument();//成员变量CFrameWndEx m_pMain