1

我从如下所示的 csv 文件中解析数据:

X,..,..,Dx,..,..
Y,..,..,Dy,..,..
X,..,..,Dx,..,..
Y,..,..,Dy,..,..
X,..,..,Dx,..,..
Y,..,..,Dy,..,..

每一行都是我定义的类型数组的一个元素,并与 FileHelpers 一起使用。这可能不相关,但我将这个包括在内,以防有人知道我可以在这个阶段使用 FileHelpers 做的一个技巧。

我只对 X,Dx 和 Y,Dy 对感兴趣 数据可能不仅仅是 X 和 Y 例如.. (X,Dx); (Y,Dy); (Z,Dz); ...

我将字母的数量称为 nL

目标是通过处理具有 SUM(nIterations) * nL 元素的所有 D 的数组来获得每个组的 Dx、Dy、... 的平均值。

我有一个迭代次数列表:

let nIterations = [2000; 2000; 2000; 1000; 500; 400; 400; 400; 300; 300]

对于这些数字中的每一个,我都会有那么多“字母组”。因此,nIterations.[0] 感兴趣的数据行是第 0 行到 (nIterations.[0] * nL)

为了获得 nIterations.[i] 感兴趣的行,我创建了一个列表“nis”,它是对 nIterations 执行的扫描操作的结果。

let nis = List.scan (fun x e -> x + e) 0 nIterations

然后隔离 nItertions.[i] 组..

let group = Array.sub Ds (nis.[i]*nL) (nIterations.[i]*nL)

这是整个事情:

nIterations |> List.mapi (fun i ni ->
    let igroup = Array.sub Ds (nis.[i]*nL) (ni*nL)
    let groupedbyLetter = (chunk nL igroup)

    let sums = seq { for idx in 0..(nL - 1) do
                         let d = seq { for g in groupedbyLetter do 
                                           yield (Seq.head (Seq.skip idx g)) }
                         yield d |> Seq.sum }

    sums |> Seq.map (fun x -> (x / (float ni))) ) |> List.ofSeq

“块”功能是我在 SO 上找到的功能:

let rec chunk n xs =
    if Seq.isEmpty xs then Seq.empty
    else
        let (ys,zs) = splitAt n xs
        Seq.append (Seq.singleton ys) (chunk n zs)

我已经验证了这项工作,并得到了我想要的 - 一个大小为 nL 的集合,大小为 nIterations.Length 集合。

问题是速度——这只适用于小数据集;我在给出的示例中使用的尺寸太大了。它在块函数中“挂起”。

所以我的问题是:我该如何提高整个过程的速度?(和/或)进行“换位”的最佳(或至少更好)方法是什么

我想我可以:

  • 尝试在我读取数据时重新排列数据
  • 尝试直接索引元素
  • 尝试将过程分解为更小的阶段或“通过”
  • ???
4

1 回答 1

1

我知道了。

let averages =
    (nIterations |> List.mapi (fun i ni ->
        let igroup = Array.sub Ds (nis.[i]*nL) (ni*nL)
        let groupedbyLetter = 
            [| for a in 1..nL..igroup.Length do 
                   yield igroup.[(a - 1)..(a - 1)+(nL-1)] |]

        [| for i in 0..(nL - 1) do
               yield [| for j in 0..(groupedbyLetter.Length - 1) do
                            yield groupedbyLetter.[j].[i] |] 
               |> Array.average |]) )

let columns = [| for i in 0..(nL - 1) do
                     yield [| for j in 0..(nIterations.Length - 1) do
                                  yield averages.[j].[i] |] 
                     |]

“列”功能只是再次转置数据,以便我可以轻松打印..

               ----Average Ds----
nIterations       X    Y    Z
   2000          0.2  0.7  1.2
    ...          ...  ...  ...
    ...          ...  ...  ...

例如平均回报

[[x1,y1,z1,..], [x2,y2,z2,..], ... ]

列给了我

[ [x1,x2,..], [y1,y2,..], [z1,z2,..], ...]
于 2013-08-20T19:51:24.427 回答