如何使用 Deedle Frame<DateTime,_> 中的某个键获取行的位置?

How to get the position of the row with some key from a Deedle Frame<DateTime,_>?

我的意思是:

let position:int = positionForKey frame key
let row =
  Frame.take positionForKey
  |> frame.takeLast 1

那么,row应该是一个只有一行的Frame,它的key是key.

我不知道的是如何实现positionForKey。一个想法应该可行但我不知道这是否是最好的方法是通过 Series.scanValues 创建另一个 Series 并让值成为位置,但我认为应该是一种更优雅的方式。

通过 Series.scanValues 的实施将是:

let positionForKey (frame:Frame<'K,_>) (key:'K) =
  let positions = Series.scanValues (fun pos _ -> pos + 1) 0 (frame.GetColumnAt 0)
  positions.[key]

... 索引从 1

开始

例子

假设您有这样的框架 f

03/01/01,  4 , ...
04/01/01,  3 , ...
05/01/01,  6 , ...
   ...  , ..., ...

然后,positionforKey f 04/01/01 = 2positionforKey f 05/01/01 = 3等等。 (假设 04/01/01 是一个有效的日期时间)

您可以通过多种方式提取键的位置,例如使用 .RowIndex。但最简单的方法可能就是获取键并找到索引。您可能想使用 TryFindIndex,其中 df 是数据帧,由 DateTime 索引。

df.RowKeys |> Seq.findIndex(fun x -> x = DateTime(2017,5,6))

如果您只想 return 指定索引处的一行,可以使用扩展方法。以下是按索引获取行的一些方法:

(Frame.getRow (DateTime(2017,5,6)) df):Series<string,string>

df.Rows.[(DateTime(2017,5,6))]

如果您想做一些更有趣的事情,您当然应该参考 Deedle, and Frame docs

Deedle 实际上有 built-in 函数来执行此操作,但它们没有很好的文档记录(主要是因为当我们添加对 "virtual frames" 的支持时这已经发生了很大变化)。

但是,考虑一个示例数据框:

let ts = series [ for i in 0 .. 365 -> DateTime(2017, 1, 1).AddDays(float i) => float i]
let df = frame ["Sample" => ts ]

数据框有一个行索引,表示如何使用索引执行查找。使用RowIndex,你可以找到key,然后将返回的地址转换为索引:

let addr = df.RowIndex.Locate(DateTime(2017, 5, 1))
let idx = df.RowIndex.AddressOperations.OffsetOf(addr)

然后你可以得到一个只有这一行的框架:

df.GetRowsAt([| int idx |])

当您使用 in-memory 数据帧时,地址 addr 只是索引,但 in virtual data frames 它会是一个编码行存储位置的数字,因此它不会直接映射到偏移量。这就是我添加 OffsetOf 调用的原因,它将地址映射到实际索引。虽然在in-memory帧的情况下,你不需要担心这个。

如果未找到密钥,addr 值将为 -1L(但原则上,检查时应使用 Addressing.Address.invalid)。