Deedle


Deedle: .NET用の探索的データライブラリ

Deedleはデータおよび時系列操作、あるいは科学計算プログラミング用のライブラリで簡単に使用できます。 このライブラリは構造的データフレーム処理、整列済みあるいは未成列データ処理、時系列データ処理を サポートしています。DeedleはF#やC#のインタラクティブコンソールを使用して行う 手探りのプログラミングに適するよう設計されていますが、コンパイル済みの.NETコードにおいても 活用できます。

ライブラリには複雑なインデクシングやスライシング、データの連結やアライメント、 値の無いデータに対する処理、グループ化や集計、統計など、多岐にわたるデータ操作が実装されています。

タイタニック号の生存者を20行のコードで分析する

タイタニック号のデータセットtitanic という名前のデータフレームとして読み込んであるとします (このデータフレームにはint型のPclassやbool型のSurvivedといった多数の列があります)。 そして乗船券の階級別に生存者の比率を計算してみましょう:

 1: 
 2: 
 3: 
 4: 
 5: 
 6: 
 7: 
 8: 
 9: 
10: 
11: 
12: 
13: 
14: 
15: 
16: 
17: 
18: 
19: 
20: 
// タイタニック号のデータを読み込み、「性別」でグループ化します
let titanic = Frame.ReadCsv(root + "titanic.csv").GroupRowsBy<int>("Pclass")

// 'Survived'列を取得して階級毎の生存者集を計算します
let byClass =
  titanic.GetColumn<bool>("Survived")
  |> Series.applyLevel fst (fun s ->
      // 'Survived'が'True'と'False'のデータを取得します
      series (Seq.countBy id s.Values))
  // 'Pclass'を行、'Died' と 'Survived' を列に持つようなフレームを作成します
  |> Frame.ofRows 
  |> Frame.sortRowsByKey
  |> Frame.indexColsWith ["Died"; "Survived"]

// タイタニック号の男性および女性の総数を持つ列を追加します
byClass?Total <- byClass?Died + byClass?Survived

// 結果をいい感じにパーセント表示するようなデータフレームを組み立てます
frame [ "死者 (%)" => round (byClass?Died / byClass?Total * 100.0)
        "生存者 (%)" => round (byClass?Survived / byClass?Total * 100.0) ]

死者 (%)

生存者 (%)

1

37

63

2

53

47

3

76

24

ここではまずデータをPclassでグループ化して、Survived列をブール値のシリーズとして取得しています。 そしてapplyLevelを使用して各グループにまとめています。 この関数は旅行者の階級毎に特定の関数を呼び出します。 今回は生存者数と死者数をカウントしています。 そして適切なラベルを付けてフレームをソートし、 いい感じのまとめとなるような新しいデータフレームを組み立てています。

Deedleの取得方法

サンプルとドキュメント

ライブラリには包括的なドキュメントが欠かせません。 チュートリアルや記事はいずれも samplesフォルダ 内の *.fsx ファイルから自動生成されています。 また、ライブラリの実装コードに記述されたMarkdownコメントを元にして、 APIリファレンスも自動生成されています。

  • クイックスタートチュートリアル ではF#データライブラリの 主要な機能の用法を紹介しています。 まずはこちらから始めましょう。 10分ほどでライブラリの用法を学習できます。

  • データフレームの機能 には一般的に使用されるデータフレームの機能について、 さらに多くの例があります。 たとえばスライシングや連結、グループ化、集計といった機能があります。

  • シリーズの機能 では(株価のような)時系列データを処理する際に 使用される機能について詳しく説明します。 たとえばスライディングウィンドウやチャンク化、サンプリングや統計といった機能があります。

  • フレームおよびシリーズ統計の計算 では平均や分散、歪度などの統計指針を 計算する方法について説明します。 またこのチュートリアルではウィンドウの移動やウィンドウ統計の拡張も行います。

  • DeedleライブラリはF#とC#いずれにおいても使用できます。 なるべくそれぞれの言語に倣ったAPIとなるようにしています。 C#フレンドリーなAPIについては DeedleをC#から使用する の ページを参照してください。

ライブラリ内にあるすべての型やモジュール、関数から自動生成されたドキュメントが APIリファレンス にあります。 また、すべてがドキュメント化されている主要なモジュールは以下の3つです:

  • Series モジュール には 各データシリーズや時系列の値を処理するための機能があります。
  • Frame モジュール には Series モジュールと似た機能が多数ありますが、いずれもデータフレーム全体を対象とするものです。
  • Stats モジュール には 標準的な統計関数やウィンドウの移動など、多数の機能があります。 このモジュールにはシリーズとフレーム両方を対象とする関数があります。

貢献方法および著作権

プロジェクトはGitHub 上でホストされており、 Issuesの報告 やプロジェクトのフォーク、プルリクエストの送信などを行うことができます。 公開用のAPIを新規に追加する場合はドキュメントとなるような サンプル も 合わせて追加するようにしてください。 ライブラリの動作については ライブラリの設計メモ を参照されるとよいでしょう。

F# とデータサイエンスに関する一般的な話題に興味があるのであれば、 F# data science and machine learning ワーキンググループに参加してみるとよいでしょう。 ここではF#用のデータサイエンスプロジェクトに関する活動を行っています。

ライブラリは BlueMountain Capital ならびに 共著者によって開発されています。 ライセンスはBSD ライセンスを採用しているため、 商用非商用問わず、変更および再配布することができます。 詳細についてはGitHubレポジトリの ライセンスファイル を参照してください。

val titanic : Frame<(int * int),string>

Full name: Index.titanic
Multiple items
module Frame

from Deedle

--------------------
type Frame =
  static member CreateEmpty : unit -> Frame<'R,'C> (requires equality and equality)
  static member FromArray2D : array:'T [,] -> Frame<int,int>
  static member FromColumns : cols:Series<'TColKey,Series<'TRowKey,'V>> -> Frame<'TRowKey,'TColKey> (requires equality and equality)
  static member FromColumns : cols:Series<'TColKey,ObjectSeries<'TRowKey>> -> Frame<'TRowKey,'TColKey> (requires equality and equality)
  static member FromColumns : columns:seq<KeyValuePair<'ColKey,ObjectSeries<'RowKey>>> -> Frame<'RowKey,'ColKey> (requires equality and equality)
  static member FromColumns : columns:seq<KeyValuePair<'ColKey,Series<'RowKey,'V>>> -> Frame<'RowKey,'ColKey> (requires equality and equality)
  static member FromColumns : rows:seq<Series<'ColKey,'V>> -> Frame<'ColKey,int> (requires equality)
  static member FromRecords : values:seq<'T> -> Frame<int,string>
  static member FromRecords : series:Series<'K,'R> -> Frame<'K,string> (requires equality)
  static member FromRowKeys : keys:seq<'K> -> Frame<'K,string> (requires equality)
  ...

Full name: Deedle.Frame

--------------------
type Frame<'TRowKey,'TColumnKey (requires equality and equality)> =
  interface IDynamicMetaObjectProvider
  interface INotifyCollectionChanged
  interface IFsiFormattable
  interface IFrame
  new : names:seq<'TColumnKey> * columns:seq<ISeries<'TRowKey>> -> Frame<'TRowKey,'TColumnKey>
  private new : rowIndex:IIndex<'TRowKey> * columnIndex:IIndex<'TColumnKey> * data:IVector<IVector> -> Frame<'TRowKey,'TColumnKey>
  member AddColumn : column:'TColumnKey * series:ISeries<'TRowKey> -> unit
  member AddColumn : column:'TColumnKey * series:seq<'V> -> unit
  member AddColumn : column:'TColumnKey * series:ISeries<'TRowKey> * lookup:Lookup -> unit
  member AddColumn : column:'TColumnKey * series:seq<'V> * lookup:Lookup -> unit
  ...

Full name: Deedle.Frame<_,_>

--------------------
new : names:seq<'TColumnKey> * columns:seq<ISeries<'TRowKey>> -> Frame<'TRowKey,'TColumnKey>
static member Frame.ReadCsv : path:string * ?hasHeaders:bool * ?inferTypes:bool * ?inferRows:int * ?schema:string * ?separators:string * ?culture:string * ?maxRows:int -> Frame<int,string>
static member Frame.ReadCsv : stream:IO.Stream * ?hasHeaders:bool * ?inferTypes:bool * ?inferRows:int * ?schema:string * ?separators:string * ?culture:string * ?maxRows:int -> Frame<int,string>
val root : string

Full name: Index.root
Multiple items
val int : value:'T -> int (requires member op_Explicit)

Full name: Microsoft.FSharp.Core.Operators.int

--------------------
type int = int32

Full name: Microsoft.FSharp.Core.int

--------------------
type int<'Measure> = int

Full name: Microsoft.FSharp.Core.int<_>
val byClass : Frame<int,string>

Full name: Index.byClass
member Frame.GetColumn : column:'TColumnKey -> Series<'TRowKey,'R>
member Frame.GetColumn : column:'TColumnKey * lookup:Lookup -> Series<'TRowKey,'R>
type bool = Boolean

Full name: Microsoft.FSharp.Core.bool
Multiple items
module Series

from Deedle

--------------------
type Series =
  static member ofNullables : values:seq<Nullable<'a0>> -> Series<int,'a0> (requires default constructor and value type and 'a0 :> ValueType)
  static member ofObservations : observations:seq<'a0 * 'a1> -> Series<'a0,'a1> (requires equality)
  static member ofOptionalObservations : observations:seq<'K * 'a1 option> -> Series<'K,'a1> (requires equality)
  static member ofValues : values:seq<'a0> -> Series<int,'a0>

Full name: Deedle.FSharpSeriesExtensions.Series

--------------------
type Series<'K,'V (requires equality)> =
  interface IFsiFormattable
  interface ISeries<'K>
  new : pairs:seq<KeyValuePair<'K,'V>> -> Series<'K,'V>
  new : keys:seq<'K> * values:seq<'V> -> Series<'K,'V>
  new : index:IIndex<'K> * vector:IVector<'V> * vectorBuilder:IVectorBuilder * indexBuilder:IIndexBuilder -> Series<'K,'V>
  member After : lowerExclusive:'K -> Series<'K,'V>
  member Aggregate : aggregation:Aggregation<'K> * observationSelector:Func<DataSegment<Series<'K,'V>>,KeyValuePair<'TNewKey,OptionalValue<'R>>> -> Series<'TNewKey,'R> (requires equality)
  member Aggregate : aggregation:Aggregation<'K> * keySelector:Func<DataSegment<Series<'K,'V>>,'TNewKey> * valueSelector:Func<DataSegment<Series<'K,'V>>,OptionalValue<'R>> -> Series<'TNewKey,'R> (requires equality)
  member AsyncMaterialize : unit -> Async<Series<'K,'V>>
  member Before : upperExclusive:'K -> Series<'K,'V>
  ...

Full name: Deedle.Series<_,_>

--------------------
new : pairs:seq<Collections.Generic.KeyValuePair<'K,'V>> -> Series<'K,'V>
new : keys:seq<'K> * values:seq<'V> -> Series<'K,'V>
new : index:Indices.IIndex<'K> * vector:IVector<'V> * vectorBuilder:Vectors.IVectorBuilder * indexBuilder:Indices.IIndexBuilder -> Series<'K,'V>
val applyLevel : level:('K1 -> 'K2) -> op:(Series<'K1,'V> -> 'R) -> series:Series<'K1,'V> -> Series<'K2,'R> (requires equality and equality)

Full name: Deedle.Series.applyLevel
val fst : tuple:('T1 * 'T2) -> 'T1

Full name: Microsoft.FSharp.Core.Operators.fst
val s : Series<(int * int),bool>
val series : observations:seq<'a * 'b> -> Series<'a,'b> (requires equality)

Full name: Deedle.FSharpSeriesExtensions.series
module Seq

from Microsoft.FSharp.Collections
val countBy : projection:('T -> 'Key) -> source:seq<'T> -> seq<'Key * int> (requires equality)

Full name: Microsoft.FSharp.Collections.Seq.countBy
val id : x:'T -> 'T

Full name: Microsoft.FSharp.Core.Operators.id
property Series.Values: seq<bool>
static member Frame.ofRows : rows:seq<'a0 * #ISeries<'a2>> -> Frame<'a0,'a2> (requires equality and equality)
static member Frame.ofRows : rows:Series<'a0,#ISeries<'a2>> -> Frame<'a0,'a2> (requires equality and equality)
val sortRowsByKey : frame:Frame<'R,'C> -> Frame<'R,'C> (requires equality and equality)

Full name: Deedle.Frame.sortRowsByKey
val indexColsWith : keys:seq<'C2> -> frame:Frame<'R,'C1> -> Frame<'R,'C2> (requires equality and equality and equality)

Full name: Deedle.Frame.indexColsWith
val frame : columns:seq<'a * #ISeries<'c>> -> Frame<'c,'a> (requires equality and equality)

Full name: Deedle.FSharpFrameExtensions.frame
val round : value:'T -> 'T (requires member Round)

Full name: Microsoft.FSharp.Core.Operators.round
Fork me on GitHub