3

株式データの 2 つのシーケンスがあり、統計を実行する他の関数に渡すことができるように、日付を並べてデータを結合しようとしています。基本的に、次のような 2 つ (またはそれ以上) のシーケンスを渡したいと思います。

sequenceA = [(float,DateTime)]
sequenceB = [(float,DateTime)]

関数に渡して、すべてのデータが DateTime によって適切に配置された単一のシーケンスを返すようにします。何かのようなもの:

return = [(float,float,DateTime)]

ここで、フロートはその DateTime の 2 つのシーケンスの終値です。

ネストされた for ループを使用してみましたが、うまくいくはずです (問題が発生しましたが) が、F# の match 式でもこれを処理できるようです。ドキュメントと一致式の例をいくつか調べましたが、乗り越えられなかったさまざまな問題に直面しています。

これは、私が達成しようとしているものの単純化されたバージョンでの私の最近の試みです。ご覧のとおり、シーケンス「x」の最初の要素の日付が「1/11/2011」かどうかを確認しようとしています。問題は、1) 常に「はい」が返されること、および 2) ここからシーケンス全体、そして最終的に 2 つ以上のシーケンスに到達する方法がわからないことです。

let x = seq[(1.0,System.DateTime.Parse("1/8/2011"));(2.0,System.DateTime.Parse("1/9/2011"))]
type t = seq<float*DateTime>    

let align (a:t) =
    let testDate = System.DateTime.Parse("1/11/2011")
    let b = Seq.head(a)
    match snd b with
        | testDate -> printfn "Yes"
        | _ -> printfn "No"

align x

私は F# に比較的慣れていませんが、これは match 式で可能であると確信しています。どんな助けでも大歓迎です!

4

3 に答える 3

2

あなたの質問には2つの部分があります:

パターン マッチングに関しては、上記のパターンでは、testDate はタプル b の 2 番目の項目にバインドされる名前です。どちらのパターンも任意の日付に一致しますが、最初のパターンが一致するため、例では常に「はい」が出力されます。

日付の特定の値で一致させたい場合は、パターンで「when」キーワードを使用できます。

let dateValue = DateTime.Today

match dateValue with
| someDate when someDate = DateTime.Today -> "Today"
| _ -> "Not Today"

align 関数を実装しなければならないとしたら、おそらくパターン マッチングは使用しないでしょう。Seq.groupBy を使用して、同じ日付のすべてのエントリを収集できます。

///Groups two sequences together by key
let align a b =

    let simplifyEntry (key, values) =
        let prices = [for value in values -> snd value]
        key, prices

    a 
    |> Seq.append b
    |> Seq.groupBy fst
    |> Seq.map simplifyEntry
    |> Seq.toList

//Demonstrate alignment of two sequences
let s1 = [DateTime.Today, 1.0]
let s2 = [
    DateTime.Today, 2.0 
    DateTime.Today.AddDays(2.0), 10.0]

let pricesByDate = align s1 s2

for day, prices in pricesByDate do
    let pricesText =
        prices
        |> Seq.map string
        |> String.concat ", "
    printfn "%A %s" day pricesText
于 2013-09-06T17:46:22.447 に答える
0

私はたまたま時系列データを操作するためのライブラリに取り組んでおり、これを行うための関数がありますDateTime * float option * float option.1つの系列が指定された日付の値を持つ場合を表すために返されるため、実際にはもう少し一般的ですが、他のものはしません。

この関数は、2 つのシリーズが既に並べ替えられていることを前提としています。つまり、それらを 1 回だけ走査する必要があります (並べ替えられていないシーケンスについては、複数の反復を行うか、いくつかの一時テーブルを作成する必要があります)。

また、例よりも引数が交換されていることに注意してください。あなたはそれを与える必要がありますDateTime * float。この関数は特に優れているわけではありませんIEnumerable。つまり、変更可能な列挙子 (および一般的に醜い命令型のもの) を使用する必要があるという意味で機能します。一般に、パターン マッチングはシーケンスではうまく機能しません。headは取得できますが、 tailは取得できません。これは効率が悪いためです。F# のリストにはもっといいものを書くことができます...

open System.Collections.Generic

let alignWithOrdering (seq1:seq<'T * 'TAddress>) (seq2:seq<'T * 'TAddress>) (comparer:IComparer<_>) = seq {
  let withIndex seq = Seq.mapi (fun i v -> i, v) seq
  use en1 = seq1.GetEnumerator()
  use en2 = seq2.GetEnumerator()
  let en1HasNext = ref (en1.MoveNext())
  let en2HasNext = ref (en2.MoveNext())
  let returnAll (en:IEnumerator<_>) hasNext f = seq { 
    if hasNext then
      yield f en.Current
      while en.MoveNext() do yield f en.Current }

  let rec next () = seq {
    if not en1HasNext.Value then yield! returnAll en2 en2HasNext.Value (fun (k, i) -> k, None, Some i)
    elif not en2HasNext.Value then yield! returnAll en1 en1HasNext.Value (fun (k, i) -> k, Some i, None)
    else
      let en1Val, en2Val = fst en1.Current, fst en2.Current
      let comparison = comparer.Compare(en1Val, en2Val)
      if comparison = 0 then 
        yield en1Val, Some(snd en1.Current), Some(snd en2.Current)
        en1HasNext := en1.MoveNext()
        en2HasNext := en2.MoveNext()
        yield! next()
      elif comparison < 0 then
        yield en1Val, Some(snd en1.Current), None
        en1HasNext := en1.MoveNext()
        yield! next ()
      else 
        yield en2Val, None, Some(snd en2.Current)
        en2HasNext := en2.MoveNext() 
        yield! next () }
  yield! next () }

文字列を (あなたの ではなく) キーとして使いたいと仮定するとDateTime、次のように呼び出すことができます:

alignWithOrdering 
    [ ("b", 0); ("c", 1); ("d", 2) ] 
    [ ("a", 0); ("b", 1); ("c", 2) ] (Comparer<string>.Default) |> List.ofSeq

// Returns 
[ ("a", None, Some 0); ("b", Some 0, Some 1); 
  ("c", Some 1, Some 2); ("d", Some 2, None) ]

F# で株式データの時系列を操作することに興味がある場合は、 F# FoundationのF# for Data and Machine Learningワーキング グループに参加することに興味があるかもしれません。私たちは現在、時系列をサポートするオープンソース ライブラリに取り組んでいます。初期プレビューを確認して貢献することに興味がある場合は、このワーキング グループを通じて行うことができます。

于 2013-09-06T17:39:44.930 に答える
0
open System
let x = seq[(1.0,System.DateTime.Parse("1/8/2011"));(2.0,DateTime.Parse("1/9/2011"))]
//type t = seq<float*DateTime>    
let (|EqualDate|_|) str dt=
  DateTime.TryParse str|>function
   |true,x when x=dt->Some()
   |_->None
let align a =
    //let testDate = System.DateTime.Parse("1/11/2011")
    let b = Seq.head(a)
    match b with
        |_,EqualDate "1/9/2011" -> printfn "Yes"
        | _ -> printfn "No"

align x
x|>Seq.skip 1|>align 
于 2013-09-06T18:17:41.790 に答える