0

这个问题可能看起来有点微不足道,它确实发生在我们的过程中,因为数据不干净。我有一个数据框看起来像

let tt = Series.ofObservations[ 1=>10.0; 3=>20.0;5=> 30.0; 6=> 40.0; ]
let tt2 = Series.ofObservations[1=>  Double.NaN; 3=> 5.5; 6=>Double.NaN  ]
let tt3 = Series.ofObservations[1=> "aaa"; 3=> "bb"; 6=>"ccc" ]
let f1 = frame ["cola" => tt; "colb"=>tt2;]
f1.AddColumn("colc", tt3)

 f1.Print();;
     cola colb      colc      
1 -> 10   <missing> aaa       
3 -> 20   5.5       bb        
5 -> 30   <missing> <missing> 
6 -> 40   <missing> ccc   

我需要过滤掉任何行,直到第一行的值在 colb

     cola colb      colc      
3 -> 20   5.5       bb        
5 -> 30   <missing> <missing> 
6 -> 40   <missing> ccc

我能想出的唯一解决方案是使用一个可变标志,它破坏了函数式编程的完整性。也许这个过滤缺失的头可以隐藏在库中。但这仍然让我怀疑我是否没有以正确的方式做到这一点。

let flag = ref false
let filteredF1 = f1 |> Frame.filterRows(fun k v -> 
                                  match !flag, v.TryGetAs<float>("colb") with 
                                  | false, OptionalValue.Missing -> flag := false
                                  | false, _ -> flag := true
                                  | true, _ -> ()
                                  !flag
                                  ) 

这实际上并不是 Deedle 的问题,而是更多地与不变性应如何实现这一点有关。在 Python 和 VBA 中很容易实现的东西在 F# 中似乎很难做到。

在这样的统计计算情况下,多个系列有不同的开始时间。在起点(保留)之后,包含缺失值的数据点很重要,因为缺失值意味着什么。

任何建议表示赞赏。卡斯比

4

2 回答 2

1

这是我的首选方式:

// find first index having non-null value in column b
let idx = 
  f1?colb 
  |> Series.observationsAll 
  |> Seq.skipWhile (function | (_, None) -> true | _ -> false) 
  |> Seq.head 
  |> fst;;

// slice frame
f1.Rows.[idx .. ];;
于 2014-08-25T14:22:35.173 回答
0

如果您将代码包装到一个函数中(我对其进行了一些修改,但根本没有对其进行测试!!)

let dropTil1stNonMissingB frame =
  let flag = ref false
  let kernel k v ->
    flag := !flag || v.TryGetAs<float>("colb").HasValue
    !flag
  Frame.filterRows kernel frame

那么你的代码看起来纯粹是功能性的:

let filteredF1 = f1 |> dropTil1stnonMissingB

只要引用的使用被限制在一个狭窄的范围内,它就应该被接受。不变性不是函数式编程的最终目标。编写好的代码只是指导原则。

事实上,Deedle 开发人员应该提供他们的Seq.foldfor版本Frame

然后,您可以将其(new Frame([],[]), false)用作初始'State. 粗略地说,您应该能够将 C、Python 或任何命令式语言中的任何循环转换为fold(又名fold_leftfoldl),尽管这不一定是要走的路。

您不妨将其定义为Frame.

type Frame with
  member frame.DropTil1stNonMissingB =
    ...

let filteredF1 = f1.DropTil1stNonMissingB
于 2014-08-22T10:51:20.820 回答