F#中的采样:设置是否足够?

时间:2013-02-26 13:14:35

标签: f# set sampling

我有一系列项目,我想从中抽样。

我的印象是,一个Set会有一个好的结构来取样,在折叠中我会回复原始或修改的集合,其中检索到的元素缺失,这取决于我是否要更换。 但是,似乎没有方法直接从Set中检索元素。

我有什么遗失的吗?或者我应该使用一组索引,以及从某个随机position < Set.count开始的代理函数,并一直向上找到一个成员?

就是这一行

module Seq =
    let modulo (n:int) start = 
        let rec next i = seq { yield (i + 1)%n ; yield! next (i+1)}
        next start

module Array =
    let Sample (withReplacement:bool) seed (entries:'T array) = 
        let prng, indexes = new Random(seed), Set(Seq.init (entries |> Array.length) id)
        Seq.unfold (fun set  -> let N = set |> Set.count
                                let next = Seq.modulo N (prng.Next(N)) |> Seq.truncate N |> Seq.tryFind(fun i -> set |> Set.exists ((=) i))
                                if next.IsSome then
                                    Some(entries.[next.Value], if withReplacement then set else Set.remove next.Value set)
                                else
                                    None)

编辑:积极跟踪我给出的内容,而不是跟踪我仍然可以提供的内容会使其更简单,更有效。

2 个答案:

答案 0 :(得分:5)

对于没有替换的的采样,您可以只是置换源seq并采用您想要采样的许多元素

let sampleWithoutReplacement n s =
    let a = Array.ofSeq s
    seq { for i = a.Length downto 1 do
              let j = rnd.Next i
              yield a.[j]
              a.[j] <- a.[i - 1] }
    |> Seq.take n

要使用替换样本,只需从源seq中选择一个随机元素n次

let sampleWithReplacement n s =
    let a = Array.ofSeq s
    Seq.init n (fun _ -> a.[rnd.Next(a.Length)])

这些可能不是使用大数据集的最有效方法

答案 1 :(得分:2)

继续我们的评论...如果你想随机抽样一个序列而不将整个事物扼杀到内存中,你可以生成一组随机索引,大小与你想要的样本一样(与你已有的不同): / p>

let rand count max = 
  System.Random() 
    |> Seq.unfold (fun r -> Some(r.Next(max), r))
    |> Seq.distinct
    |> Seq.take count
    |> set

let takeSample sampleSize inputSize input =
  let indices = rand sampleSize inputSize
  input
    |> Seq.mapi (fun idx x -> 
      if Set.contains idx indices then Some x else None)
    |> Seq.choose id

let inputSize = 100000
let input = Seq.init inputSize id
let sample = takeSample 50 inputSize input
printfn "%A" (Seq.toList sample)