F# Data


F# Data: CSV パーサーおよびリーダー

F#の CSV 型プロバイダー はF#で作成された 効率の良いCSVパーサーを元にしています。 また、動的に値にアクセスできるような単純なAPIも備えられています。

厳密に定義されたCSV形式のドキュメントを扱う場合には、 型プロバイダー を使用したほうが簡単です。 しかし動的アクセスが必要になるシナリオや、 単純なスクリプトを手軽に作成したい場合には パーサーを直接使ったほうがおそらくは簡単でしょう。

CSVドキュメントの読み取り

サンプルとなるCSVドキュメントを読み込むには、まず (F# Interactiveを使用している場合は) FSharp.Data.dll への参照を追加するか、 プロジェクトで参照を追加する必要があります。

1: 
2: 
#r "../../../../bin/FSharp.Data.dll"
open FSharp.Data

FSharp.Data 名前空間には CsvFile 型が含まれていて、 この型ではデータの読み取り用に2つのstaticメソッドが公開されています。 Parse メソッドはデータを string 型の値として指定できます。 Load メソッドはデータをファイルあるいはWeb上のリソースから読み取ることができます (また、非同期バージョンの LoadAsync もあります)。 以下の例ではYahoo financeのウェブサイトにある実際のCSVファイルのURLを指定して Load メソッドを呼び出しています:

1: 
2: 
3: 
4: 
5: 
6: 
// 株価データをダウンロード
let msft = CsvFile.Load("http://ichart.finance.yahoo.com/table.csv?s=MSFT").Cache()

// HLOC形式で株価を表示
for row in msft.Rows do
  printfn "HLOC: (%s, %s, %s)" (row.GetColumn "High") (row.GetColumn "Low") (row.GetColumn "Date")

CsvProvider とは異なり、 CsvFile はパフォーマンスを上げるために ストリーミングモードで動作します。 つまり Rows は1度だけしか走査できません。 複数回走査する必要がある場合には Cache メソッドを使用することになります。 ただしこのメソッドはメモリを多く使用するため、 巨大なデータセットを処理する場合には使用すべきではありません。

CSV の拡張機能を使用する

ここでは FSharp.Data.CsvExtensions 名前空間をオープンすることで 使用できるようになる拡張機能について説明します。 この名前空間をオープンすると以下のような記述ができるようになります:

  • row?column という動的演算子を使うと column 列の値を取得できます。 あるいは row.[column] というインデクサ形式でも取得できます。
  • value.AsBoolean() は値が true または false であれば それをブール値として返します。
  • value.AsInteger() は値が数値型であり、整数として変換可能であれば それを整数値として返します。 同じように value.AsInteger64()value.AsDecimal()value.AsFloat() といったメソッドもあります。
  • value.AsDateTime()ISO 8601 形式か、あるいは1970/1/1からのミリ秒を含んだ \/Date(...)\/ JSON 形式の値を DateTime として返します。
  • value.AsGuid() は値を Guid として返します。

数値あるいは日付の値をパースする必要があるメソッドには 省略可能なパラメータとしてカルチャを指定できます。

以下の例では先ほどのCSVをサンプルにして これらの拡張メソッドを呼び出しています:

1: 
2: 
3: 
4: 
open FSharp.Data.CsvExtensions

for row in msft.Rows do
  printfn "HLOC: (%f, %M, %O)" (row.["High"].AsFloat()) (row?Low.AsDecimal()) (row?Date.AsDateTime())

CSVファイルを変形する

CsvFiles は読み取りだけではなく、CSVファイルの変形もサポートしています。 Filter Take TakeWhile Skip SkipWhile Truncate といった操作が可能です。 変形後は Save メソッドのオーバーロードのいずれかを使って結果を保存できます。 保存時には別の区切り文字やクォート文字を指定できます。

1: 
2: 
3: 
4: 
// 終値が始値よりも高いもののうち、上位10位の株価をTSV(タブ区切り)形式で保存します:
msft.Filter(fun row -> row?Close.AsFloat() > row?Open.AsFloat())
    .Truncate(10)
    .SaveToString('\t')

関連する記事

namespace FSharp
namespace FSharp.Data
val msft : Runtime.CsvFile<CsvRow>

Full name: CsvFile.msft
type CsvFile =
  inherit CsvFile<CsvRow>
  private new : readerFunc:Func<TextReader> * ?separators:string * ?quote:char * ?hasHeaders:bool * ?ignoreErrors:bool -> CsvFile
  member private GetColumnIndex : columnName:string -> int
  static member AsyncLoad : uri:string * ?separators:string * ?quote:char * ?hasHeaders:bool * ?ignoreErrors:bool -> Async<CsvFile>
  static member Load : uri:string * ?separators:string * ?quote:char * ?hasHeaders:bool * ?ignoreErrors:bool -> CsvFile
  static member Load : reader:TextReader * ?separators:string * ?quote:char * ?hasHeaders:bool * ?ignoreErrors:bool -> CsvFile
  static member Load : stream:Stream * ?separators:string * ?quote:char * ?hasHeaders:bool * ?ignoreErrors:bool -> CsvFile
  static member Parse : text:string * ?separators:string * ?quote:char * ?hasHeaders:bool * ?ignoreErrors:bool -> CsvFile

Full name: FSharp.Data.CsvFile
static member CsvFile.Load : uri:string * ?separators:string * ?quote:char * ?hasHeaders:bool * ?ignoreErrors:bool -> CsvFile
static member CsvFile.Load : reader:System.IO.TextReader * ?separators:string * ?quote:char * ?hasHeaders:bool * ?ignoreErrors:bool -> CsvFile
static member CsvFile.Load : stream:System.IO.Stream * ?separators:string * ?quote:char * ?hasHeaders:bool * ?ignoreErrors:bool -> CsvFile
val row : CsvRow
property Runtime.CsvFile.Rows: seq<CsvRow>
val printfn : format:Printf.TextWriterFormat<'T> -> 'T

Full name: Microsoft.FSharp.Core.ExtraTopLevelOperators.printfn
member CsvRow.GetColumn : columnName:string -> string
member CsvRow.GetColumn : index:int -> string
module CsvExtensions

from FSharp.Data
member Runtime.CsvFile.Filter : predicate:System.Func<'RowType,bool> -> Runtime.CsvFile<'RowType>
Fork me on GitHub