F# Data


F# Data: WorldBank プロバイダー

世界銀行 (World Bank)は世界中の発展途上国に対して、 経済的かつ技術的な支援を行っている国際組織です。 また、世界銀行は活動の一環として世界中の各国における発展指標や その他のデータを収集しています。 data catalog のページではプログラムからも アクセスできる8000以上の指標が公開されています。

WorldBank 型プロバイダーを使うと、F#プログラムやスクリプトから型安全かつ 簡単な方法でWorldBankのデータにアクセスできるようになります。 このドキュメントはこの型プロバイダーの基本的な部分のみ説明しています。 WorldBank 型プロバイダーは Try F# の Webサイトにある"Data Science" のチュートリアルでも使われているため、 そちらも参考にするとよいでしょう。

型プロバイダーの基本

以下の例では(F# Interactive上で) FSharp.Data.dll ライブラリを読み込んだ後、 GetDataContext メソッドを使ってWorldBankへの接続を初期化し、 イギリスで大学に進学した人口の割合を受信しています;

1: 
2: 
3: 
4: 
5: 
6: 
7: 
8: 
9: 
#r "../../../../bin/FSharp.Data.dll"
open FSharp.Data

let data = WorldBankData.GetDataContext()

data
  .Countries.``United Kingdom``
  .Indicators.``School enrollment, tertiary (% gross)``
|> Seq.maxBy fst

データコンテキストが生成されると、WorldBank 型プロバイダーは 世界銀行で把握されているすべての国のリスト、および 利用可能なすべての指針のリストを受信します。 それぞれはプロパティとして参照できるようになっているため、 自動コンプリートの候補から様々なデータソースが利用できることが確認できるでしょう。 多くの指標には長い名前がつけられているため、 名前を \`` で囲む必要があります。

School enrollment, tertiary (% gross) プロパティの結果は 異なる年毎の値のシーケンスです。 Seq.maxBy fst とすることで直近で利用可能な最新のデータを取得できます。

世界銀行のデータをチャート表示する

FSharp.Charting ライブラリを使うと 大学進学率の変遷を簡単に図表にできます:

1: 
2: 
#load "../../../../packages/FSharp.Charting.0.90.6/FSharp.Charting.fsx"
open FSharp.Charting
1: 
2: 
3: 
data.Countries.``United Kingdom``
    .Indicators.``School enrollment, tertiary (% gross)``
|> Chart.Line

Chart.Line 関数はXとYの値ペアのシーケンスを受け取ります。 そのため、世界銀行から受信したデータセットをそのまま渡せば Xが年、Yがその年の値になったチャートが作成できます。

Chart

世界銀行のデータを非同期的に使う

非常に大量のデータをダウンロードする必要がある場合、 あるいは呼び出し元をブロックせずに処理を実行した場合には、 F#の非同期ワークフローを使って操作ができればいいなと思うのではないでしょうか。 F# Dataライブラリには様々なstatic引数を受け取るような WorldBankDataProvider 型があります。 引数 Asyncronoustrue にすると、 すべての操作を非同期的に実行するような型が 型プロバイダーによって生成されます:

1: 
2: 
type WorldBank = WorldBankDataProvider<"World Development Indicators", Asynchronous=true>
WorldBank.GetDataContext()

上のコードではデータソース(一般的に利用可能な指標のコレクション)の名前として "World Development Indicators" を指定して、オプション引数 Asynchronoustrue を設定しています。 そうするとたとえば School enrollment, tertiary (% gross) などのプロパティが Async<(int * int)[]> になります。 これはつまり非同期的に処理を始めることができ、最終的にデータを生成するような 操作であることを示しています。

データを並列にダウンロードする

非同期バージョンの型プロバイダーのデモとして、 多数の国における大学進学率を並列にダウンロートしてみます。 まずデータコンテキストを作成した後に、 対象とする国を配列として定義します:

 1: 
 2: 
 3: 
 4: 
 5: 
 6: 
 7: 
 8: 
 9: 
10: 
11: 
12: 
13: 
14: 
15: 
16: 
17: 
18: 
let wb = WorldBank.GetDataContext()

// 対象とする国のリストを作成
let countries = 
 [| wb.Countries.``Arab World``
    wb.Countries.``European Union``
    wb.Countries.Australia
    wb.Countries.Brazil
    wb.Countries.Canada
    wb.Countries.Chile
    wb.Countries.``Czech Republic``
    wb.Countries.Denmark
    wb.Countries.France
    wb.Countries.Greece
    wb.Countries.``Low income``
    wb.Countries.``High income``
    wb.Countries.``United Kingdom``
    wb.Countries.``United States`` |]

データを並列にダウンロードするには、非同期計算のリストを作成した後、 それらを Async.Parallel で組み合わせ、 (1つになった)計算を実行してすべてのダウンロード処理を行います:

1: 
2: 
3: 
4: 
5: 
6: 
[ for c in countries ->
    c.Indicators.``School enrollment, tertiary (% gross)`` ]
|> Async.Parallel
|> Async.RunSynchronously
|> Array.map Chart.Line
|> Chart.Combine

上のコードは単に Async.RunSynchronously を使ってダウンロードするだけではなく、 それぞれのデータセットから1つの折れ線チャートを出力して、 各チャートを Chart.Combine で1つの総合チャートにしています。

Chart

関連する記事

namespace FSharp
namespace FSharp.Data
val data : WorldBankData.ServiceTypes.WorldBankDataService

Full name: WorldBank.data
type WorldBankData =
  static member GetDataContext : unit -> WorldBankDataService
  nested type ServiceTypes

Full name: FSharp.Data.WorldBankData


<summary>Typed representation of WorldBank data. See http://www.worldbank.org for terms and conditions.</summary>
WorldBankData.GetDataContext() : WorldBankData.ServiceTypes.WorldBankDataService
module Seq

from Microsoft.FSharp.Collections
val maxBy : projection:('T -> 'U) -> source:seq<'T> -> 'T (requires comparison)

Full name: Microsoft.FSharp.Collections.Seq.maxBy
val fst : tuple:('T1 * 'T2) -> 'T1

Full name: Microsoft.FSharp.Core.Operators.fst
namespace FSharp.Charting
property WorldBankData.ServiceTypes.WorldBankDataService.Countries: WorldBankData.ServiceTypes.Countries
type Chart =
  static member Area : data:seq<#value> * ?Name:string * ?Title:string * ?Labels:#seq<string> * ?Color:Color * ?XTitle:string * ?YTitle:string -> GenericChart
  static member Area : data:seq<#key * #value> * ?Name:string * ?Title:string * ?Labels:#seq<string> * ?Color:Color * ?XTitle:string * ?YTitle:string -> GenericChart
  static member Bar : data:seq<#value> * ?Name:string * ?Title:string * ?Labels:#seq<string> * ?Color:Color * ?XTitle:string * ?YTitle:string -> GenericChart
  static member Bar : data:seq<#key * #value> * ?Name:string * ?Title:string * ?Labels:#seq<string> * ?Color:Color * ?XTitle:string * ?YTitle:string -> GenericChart
  static member BoxPlotFromData : data:seq<#key * #seq<'a2>> * ?Name:string * ?Title:string * ?Color:Color * ?XTitle:string * ?YTitle:string * ?Percentile:int * ?ShowAverage:bool * ?ShowMedian:bool * ?ShowUnusualValues:bool * ?WhiskerPercentile:int -> GenericChart (requires 'a2 :> value)
  static member BoxPlotFromStatistics : data:seq<#key * #value * #value * #value * #value * #value * #value> * ?Name:string * ?Title:string * ?Labels:#seq<string> * ?Color:Color * ?XTitle:string * ?YTitle:string * ?Percentile:int * ?ShowAverage:bool * ?ShowMedian:bool * ?ShowUnusualValues:bool * ?WhiskerPercentile:int -> GenericChart
  static member Bubble : data:seq<#value * #value> * ?Name:string * ?Title:string * ?Labels:#seq<string> * ?Color:Color * ?XTitle:string * ?YTitle:string * ?BubbleMaxSize:int * ?BubbleMinSize:int * ?BubbleScaleMax:float * ?BubbleScaleMin:float * ?UseSizeForLabel:bool -> GenericChart
  static member Bubble : data:seq<#key * #value * #value> * ?Name:string * ?Title:string * ?Labels:#seq<string> * ?Color:Color * ?XTitle:string * ?YTitle:string * ?BubbleMaxSize:int * ?BubbleMinSize:int * ?BubbleScaleMax:float * ?BubbleScaleMin:float * ?UseSizeForLabel:bool -> GenericChart
  static member Candlestick : data:seq<#value * #value * #value * #value> * ?Name:string * ?Title:string * ?Labels:#seq<string> * ?Color:Color * ?XTitle:string * ?YTitle:string -> CandlestickChart
  static member Candlestick : data:seq<#key * #value * #value * #value * #value> * ?Name:string * ?Title:string * ?Labels:#seq<string> * ?Color:Color * ?XTitle:string * ?YTitle:string -> CandlestickChart
  ...

Full name: FSharp.Charting.Chart
static member Chart.Line : data:seq<#value> * ?Name:string * ?Title:string * ?Labels:#seq<string> * ?Color:System.Drawing.Color * ?XTitle:string * ?YTitle:string -> ChartTypes.GenericChart
static member Chart.Line : data:seq<#key * #value> * ?Name:string * ?Title:string * ?Labels:#seq<string> * ?Color:System.Drawing.Color * ?XTitle:string * ?YTitle:string -> ChartTypes.GenericChart
type WorldBank = WorldBankDataProvider<...>

Full name: WorldBank.WorldBank
type WorldBankDataProvider

Full name: FSharp.Data.WorldBankDataProvider


<summary>Typed representation of WorldBank data with additional configuration parameters. See http://www.worldbank.org for terms and conditions.</summary>
                        <param name='Sources'>The World Bank data sources to include, separated by semicolons. Defaults to `World Development Indicators;Global Financial Development`.
                        If an empty string is specified, includes all data sources.</param>
                        <param name='Asynchronous'>Generate asynchronous calls. Defaults to false.</param>
WorldBankDataProvider<...>.GetDataContext() : WorldBankDataProvider<...>.ServiceTypes.WorldBankDataService
val wb : WorldBankDataProvider<...>.ServiceTypes.WorldBankDataService

Full name: WorldBank.wb
val countries : WorldBankDataProvider<...>.ServiceTypes.Country []

Full name: WorldBank.countries
property WorldBankDataProvider<...>.ServiceTypes.WorldBankDataService.Countries: WorldBankDataProvider<...>.ServiceTypes.Countries
property WorldBankDataProvider<...>.ServiceTypes.Countries.Australia: WorldBankDataProvider<...>.ServiceTypes.Country


The data for country 'Australia'
property WorldBankDataProvider<...>.ServiceTypes.Countries.Brazil: WorldBankDataProvider<...>.ServiceTypes.Country


The data for country 'Brazil'
property WorldBankDataProvider<...>.ServiceTypes.Countries.Canada: WorldBankDataProvider<...>.ServiceTypes.Country


The data for country 'Canada'
property WorldBankDataProvider<...>.ServiceTypes.Countries.Chile: WorldBankDataProvider<...>.ServiceTypes.Country


The data for country 'Chile'
property WorldBankDataProvider<...>.ServiceTypes.Countries.Denmark: WorldBankDataProvider<...>.ServiceTypes.Country


The data for country 'Denmark'
property WorldBankDataProvider<...>.ServiceTypes.Countries.France: WorldBankDataProvider<...>.ServiceTypes.Country


The data for country 'France'
property WorldBankDataProvider<...>.ServiceTypes.Countries.Greece: WorldBankDataProvider<...>.ServiceTypes.Country


The data for country 'Greece'
val c : WorldBankDataProvider<...>.ServiceTypes.Country
property WorldBankDataProvider<...>.ServiceTypes.Country.Indicators: WorldBankDataProvider<...>.ServiceTypes.Indicators


<summary>The indicators for the country</summary>
Multiple items
type Async
static member AsBeginEnd : computation:('Arg -> Async<'T>) -> ('Arg * AsyncCallback * obj -> IAsyncResult) * (IAsyncResult -> 'T) * (IAsyncResult -> unit)
static member AwaitEvent : event:IEvent<'Del,'T> * ?cancelAction:(unit -> unit) -> Async<'T> (requires delegate and 'Del :> Delegate)
static member AwaitIAsyncResult : iar:IAsyncResult * ?millisecondsTimeout:int -> Async<bool>
static member AwaitTask : task:Task<'T> -> Async<'T>
static member AwaitWaitHandle : waitHandle:WaitHandle * ?millisecondsTimeout:int -> Async<bool>
static member CancelDefaultToken : unit -> unit
static member Catch : computation:Async<'T> -> Async<Choice<'T,exn>>
static member FromBeginEnd : beginAction:(AsyncCallback * obj -> IAsyncResult) * endAction:(IAsyncResult -> 'T) * ?cancelAction:(unit -> unit) -> Async<'T>
static member FromBeginEnd : arg:'Arg1 * beginAction:('Arg1 * AsyncCallback * obj -> IAsyncResult) * endAction:(IAsyncResult -> 'T) * ?cancelAction:(unit -> unit) -> Async<'T>
static member FromBeginEnd : arg1:'Arg1 * arg2:'Arg2 * beginAction:('Arg1 * 'Arg2 * AsyncCallback * obj -> IAsyncResult) * endAction:(IAsyncResult -> 'T) * ?cancelAction:(unit -> unit) -> Async<'T>
static member FromBeginEnd : arg1:'Arg1 * arg2:'Arg2 * arg3:'Arg3 * beginAction:('Arg1 * 'Arg2 * 'Arg3 * AsyncCallback * obj -> IAsyncResult) * endAction:(IAsyncResult -> 'T) * ?cancelAction:(unit -> unit) -> Async<'T>
static member FromContinuations : callback:(('T -> unit) * (exn -> unit) * (OperationCanceledException -> unit) -> unit) -> Async<'T>
static member Ignore : computation:Async<'T> -> Async<unit>
static member OnCancel : interruption:(unit -> unit) -> Async<IDisposable>
static member Parallel : computations:seq<Async<'T>> -> Async<'T []>
static member RunSynchronously : computation:Async<'T> * ?timeout:int * ?cancellationToken:CancellationToken -> 'T
static member Sleep : millisecondsDueTime:int -> Async<unit>
static member Start : computation:Async<unit> * ?cancellationToken:CancellationToken -> unit
static member StartAsTask : computation:Async<'T> * ?taskCreationOptions:TaskCreationOptions * ?cancellationToken:CancellationToken -> Task<'T>
static member StartChild : computation:Async<'T> * ?millisecondsTimeout:int -> Async<Async<'T>>
static member StartChildAsTask : computation:Async<'T> * ?taskCreationOptions:TaskCreationOptions -> Async<Task<'T>>
static member StartImmediate : computation:Async<unit> * ?cancellationToken:CancellationToken -> unit
static member StartWithContinuations : computation:Async<'T> * continuation:('T -> unit) * exceptionContinuation:(exn -> unit) * cancellationContinuation:(OperationCanceledException -> unit) * ?cancellationToken:CancellationToken -> unit
static member SwitchToContext : syncContext:SynchronizationContext -> Async<unit>
static member SwitchToNewThread : unit -> Async<unit>
static member SwitchToThreadPool : unit -> Async<unit>
static member TryCancelled : computation:Async<'T> * compensation:(OperationCanceledException -> unit) -> Async<'T>
static member CancellationToken : Async<CancellationToken>
static member DefaultCancellationToken : CancellationToken

Full name: Microsoft.FSharp.Control.Async

--------------------
type Async<'T>

Full name: Microsoft.FSharp.Control.Async<_>
static member Async.Parallel : computations:seq<Async<'T>> -> Async<'T []>
static member Async.RunSynchronously : computation:Async<'T> * ?timeout:int * ?cancellationToken:System.Threading.CancellationToken -> 'T
module Array

from Microsoft.FSharp.Collections
val map : mapping:('T -> 'U) -> array:'T [] -> 'U []

Full name: Microsoft.FSharp.Collections.Array.map
static member Chart.Combine : charts:seq<ChartTypes.GenericChart> -> ChartTypes.GenericChart
Fork me on GitHub