在 F# 中按数值范围分组

Group by Numerical Ranges in F#

如何在 F# 中按数值范围分组 and/or Deedle。 IE。我正在查看以英尺为单位的数据,我想分组为 500 英尺的桶

例如

我有这样的数据

5000 5200 5700 5800 6100 6200 6300

我想要群组

{5000, 5200} {5700, 5800} {6100, 6200, 6300}

"buckets of 500ft" 不是很清楚你的意思。如果我假设一个 "bucket" 被定义为一个范围 500*N .. 500*(N+1),其中 N 是一个整数,那么你可以很容易地通过 integer 获得给定数字所属的桶的索引除以 500。然后您可以按该索引分组:

let data = [5000; 5200; 5700; 5800; 6100; 6200; 6300]
let groups = data |> Seq.groupBy (fun x -> x/500)

> 
val groups : seq<int * seq<int>> =
  seq
    [(10, seq [5000; 5200]); (11, seq [5700; 5800]);
     (12, seq [6100; 6200; 6300])]

正如你在问题中提到的迪德尔,我将根据迪德尔系列添加一个答案。如果您有一些观察并希望根据键(例如观察时间)对数据进行分组,这将很有用。假设我们有:

let obs = series [ 5000 => 1.0; 5200 => 2.0; 5700 => 3.0; 5800 => 4.0; 
                   6100 => 5.0; 6200 => 6.0; 6300 => 7.0 ]

现在您可以使用以下方法为每个桶创建一个包含一系列值的系列:

obs |> Series.chunkWhile (fun k1 k2 -> k1/500 = k2/500)

这与 Fyodor 的回答中的技巧相同 - 只要密钥除以 500 对于存储桶中的所有项目都相同,我们就会将其保存在一个存储桶中。

如果您想做一些进一步的计算,例如获取系列每个起点的每个桶的平均值,这将很有用:

obs 
|> Series.chunkWhile (fun k1 k2 -> k1/500=k2/500)
|> Series.mapKeys (fun k -> (k / 500) * 500)
|> Series.mapValues Stats.mean

但是,如果您只对计算问题中的组感兴趣,那么 Deedle 可能有点矫枉过正。