DenseMatrix无效分配

pro*_*rth 0 f# mathnet-numerics

不确定如何填充DenseMatrix类型:

let rows = [|for line in File.ReadAllLines("Z:\\mypath.csv") 
            |> Seq.skip 1 do yield line.Split(',') |> Array.map float|]
let data = DenseMatrix.ofRowArrays rows
let mutable data_logdiff = DenseMatrix.zero<float> (data.RowCount-1) (data.ColumnCount)

for i in [0 .. data.ColumnCount-1] do
    for j in [1 .. data.RowCount-1] do
        data_logdiff.At(j-1, i) <- data.At(j, i) / data.At(j-1, i) |> log
Run Code Online (Sandbox Code Playgroud)

最后一行生成错误"无效分配".

还想知道是否有一种功能性的方式来表达上面的逻辑.

谢谢.

Gus*_*Gus 6

我假设您使用的是MathNet,不知道哪个版本.

首先,我不认为你的data_logdiff需要是可变的,它已经是一个具有你可以变异的属性的对象,我的意思是你要改变它的属性,而不是对象本身.

然后代码中的问题是你如何改变这些属性,你应该使用索引器而不是.At只返回值:

#r @"packages\MathNet.Numerics.3.8.0\lib\net40\MathNet.Numerics.dll"
#r @"packages\MathNet.Numerics.FSharp.3.8.0\lib\net40\MathNet.Numerics.FSharp.dll"

open System.IO
open MathNet.Numerics.LinearAlgebra

let rows = [|for line in File.ReadAllLines("Z:\\mypath.csv") 
        |> Seq.skip 1 do yield line.Split(',') |> Array.map float|]
let data = DenseMatrix.ofRowArrays rows
let data_logdiff = DenseMatrix.zero<float> (data.RowCount-1) (data.ColumnCount)

for i in [0 .. data.ColumnCount-1] do
    for j in [1 .. data.RowCount-1] do
        data_logdiff.[j-1, i] <- data.At(j, i) / data.At(j-1, i) |> log
Run Code Online (Sandbox Code Playgroud)

为了使它更具功能性,请使用DenseMatrix.init而不是DenseMatrix.zero循环:

let data_logdiff = 
    DenseMatrix.init 
        (data.RowCount-1) 
        (data.ColumnCount) 
        (fun j i -> if j = 0 then 0. else data.At(j, i) / data.At(j-1, i) |> log)
Run Code Online (Sandbox Code Playgroud)

一般来说,每次使用.zero和循环来初始化矩阵或向量时,请考虑使用.init函数,这需要一个额外的参数,就像循环体.