Column/Validation Deedle 保证

Column/Validation guarantees with Deedle

有没有办法表达数据框已经过验证的概念?我能想到的最好方法是创建一个包装器类型来限制访问。我欢迎任何建议。

简单示例:

#r "nuget: Deedle"

open Deedle

type CustomFrame = 
    | Some of Frame<int,string>
    | None
let map mapping option = match option with None -> None | Some x -> Some (mapping x)
let iter action option = match option with None -> () | Some x -> action x

let parse (df:Frame<_,_>) = 
    let keys = df.ColumnKeys |> Set.ofSeq
    if keys.Contains("Entry") && keys.Contains("Color") then
        df    
        |> Frame.indexRowsInt "Entry"
        |> CustomFrame.Some
    else
    CustomFrame.None

let go (df:CustomFrame) =
    df
    |> map (Frame.filterRowsBy "Color" "Red")

let data = "Entry;Color;N\n1;Red;7\n2;Blue;42\n3;Blue;21"
let bytes = System.Text.Encoding.UTF8.GetBytes data
let stream =  new MemoryStream( bytes )

Frame.ReadCsv(stream = stream,separators = ";",hasHeaders = true)
|> parse
|> go
|> iter (fun d-> d.Print())
     Color N 
1 -> Red   7 

两条建议:

  • parse return 标准 Option 值,正如 Fyodor 所建议的那样。
  • Short-circuit 验证失败时的计算。换句话说,如果 parse returns None,根本不要调用 goiter

如果你真的想在 parse 之后进行防御性编程,并且不需要进一步验证,你不再需要 None 值。因此,您可以使用简化的包装器类型来确保始终拥有经过验证的框架:

type ValidFrame = Valid of Frame<int,string>

let map f (Valid df) = f df |> Valid
let iter (f : _ -> unit) (Valid df) = f df
let go = map (Frame.filterRowsBy "Color" "Red")

然后像这样使用它:

Frame.ReadCsv(stream = stream,separators = ";",hasHeaders = true)
|> parse
|> Option.map (
    Valid
      >> go
      >> iter (fun df -> df.Print()))

但是,就我个人而言,除非有令人信服的理由,否则我认为包装器类型有点矫枉过正。