F#、Deedle 和 OptionalValue:对象必须实现 IConvertible 错误
F#, Deedle and OptionalValue: Object must implement IConvertible error
当我尝试在框架中创建缺失值并稍后对它们执行操作时,我遇到了麻烦。这是一个 "working" 示例:
open Deedle
open System.Text.RegularExpressions
do fsi.AddPrinter(fun (printer:Deedle.Internal.IFsiFormattable) -> "\n" + (printer.Format()))
module Frame = let mapAddCol col f frame = frame |> Frame.addCol col (Frame.mapRowValues f frame)
[ {|Desc = "A - 1.50ml"; ``Price ($)`` = 23.|}
{|Desc = "B - 2ml"; ``Price ($)`` = 18.5|}
{|Desc = "C"; ``Price ($)`` = 25.|} ]
|> Frame.ofRecords
(*
Desc Price ($)
0 -> A - 1.50ml 23
1 -> B - 2ml 18.5
2 -> C 25
*)
|> Frame.mapAddCol "Volume (ml)" (fun row ->
match Regex.Match(row.GetAs<string>("Desc"),"[\d\.]+").Value with
| "" -> OptionalValue.Missing
| n -> n |> float |> OptionalValue)
(*
Desc Price ($) Volume (ml)
0 -> A - 1.50ml 23 1.5
1 -> B - 2ml 18.5 2
2 -> C 25 <missing>
*)
|> fun df -> df?``Price ($/ml)`` <- df?``Price ($)`` / df?``Volume (ml)``
//error message: System.InvalidCastException: Object must implement IConvertible.
这种方法有什么问题?
Deedle 在内部存储一个标志,判断值是否存在。这通常通过 OptionalValue
类型公开,但内部表示实际上并未使用此类型。
当您使用 mapRowValues
等函数生成新数据时,Deedle 需要识别丢失了哪些数据。这种情况仅在有限的情况下发生。当您 return OptionalValue<float>
时,Deedle 实际上会生成一个值类型为 OptionalValue<float>
而不是 float
的序列(类型系统不允许它做任何其他事情)。
对于float
的值,解决办法就是将returnnan
作为你的缺失值:
|> Frame.mapAddCol "Volume (ml)" (fun row ->
match Regex.Match(row.GetAs<string>("Desc"),"[\d\.]+").Value with
| "" -> nan
| n -> n |> float )
这将创建一系列新的 float
值,然后您可以使用 ?
运算符访问这些值。
当我尝试在框架中创建缺失值并稍后对它们执行操作时,我遇到了麻烦。这是一个 "working" 示例:
open Deedle
open System.Text.RegularExpressions
do fsi.AddPrinter(fun (printer:Deedle.Internal.IFsiFormattable) -> "\n" + (printer.Format()))
module Frame = let mapAddCol col f frame = frame |> Frame.addCol col (Frame.mapRowValues f frame)
[ {|Desc = "A - 1.50ml"; ``Price ($)`` = 23.|}
{|Desc = "B - 2ml"; ``Price ($)`` = 18.5|}
{|Desc = "C"; ``Price ($)`` = 25.|} ]
|> Frame.ofRecords
(*
Desc Price ($)
0 -> A - 1.50ml 23
1 -> B - 2ml 18.5
2 -> C 25
*)
|> Frame.mapAddCol "Volume (ml)" (fun row ->
match Regex.Match(row.GetAs<string>("Desc"),"[\d\.]+").Value with
| "" -> OptionalValue.Missing
| n -> n |> float |> OptionalValue)
(*
Desc Price ($) Volume (ml)
0 -> A - 1.50ml 23 1.5
1 -> B - 2ml 18.5 2
2 -> C 25 <missing>
*)
|> fun df -> df?``Price ($/ml)`` <- df?``Price ($)`` / df?``Volume (ml)``
//error message: System.InvalidCastException: Object must implement IConvertible.
这种方法有什么问题?
Deedle 在内部存储一个标志,判断值是否存在。这通常通过 OptionalValue
类型公开,但内部表示实际上并未使用此类型。
当您使用 mapRowValues
等函数生成新数据时,Deedle 需要识别丢失了哪些数据。这种情况仅在有限的情况下发生。当您 return OptionalValue<float>
时,Deedle 实际上会生成一个值类型为 OptionalValue<float>
而不是 float
的序列(类型系统不允许它做任何其他事情)。
对于float
的值,解决办法就是将returnnan
作为你的缺失值:
|> Frame.mapAddCol "Volume (ml)" (fun row ->
match Regex.Match(row.GetAs<string>("Desc"),"[\d\.]+").Value with
| "" -> nan
| n -> n |> float )
这将创建一系列新的 float
值,然后您可以使用 ?
运算符访问这些值。