Search code examples
.netfunctional-programmingf#deedler.net

F#, Deddle and R.Net: seq<'a> [] vs. IEnumerable array


I’m trying to convert a Deedle Frame into an R DataFrame using R.Net.

I tried 3 different approaches:

open RDotNet

REngine.SetEnvironmentVariables(@"C:\Program Files\R\R-3.6.3\bin\x64",@"C:\Program Files\R\R-3.6.3")

let engine = REngine.GetInstance()

//Deedle with columns x and y and with all the values as floats
let d = Frame.ReadCsv(@"C:\Users\flavi\Downloads\test.txt")

let a1 =
    ([],d.ColumnKeys)
    ||> Seq.fold (fun acc elem -> (d |> Frame.getCol elem |> Series.values |> Seq.map float)::acc) |> List.toArray

let a2 =
    [|
        d |> Frame.getCol "x" |> Series.values |> Seq.map float
        d |> Frame.getCol "y" |> Series.values |> Seq.map float
    |]

let (a3 : IEnumerable array) =
    [|
        d |> Frame.getCol "x" |> Series.values |> Seq.map float
        d |> Frame.getCol "y" |> Series.values |> Seq.map float
    |]

//only works with a3
let rFrame = engine.CreateDataFrame(a3,d.ColumnKeys |> Seq.map string |> Seq.toArray)

a1 (the one I would like to use) and a2 have the same signature: seq < float > []. a3 is the same as a2, the only difference being the “forced” signature of IEnumerable array. Only a3 works, but the way a3 was created is not good, since I have to insert all the columns by hand.

My questions are: 1) why only a3 works?; 2) how can I recreate a3 like a1, i.e., not having to know beforehand all the columns that exist and having IEnumerable array as signature?


Solution

  • CreateDataFrame() wants an array of IEnumerable, but a1 is an array of seq<float>, which is F#'s way of saying IEnumerable<float>; you just need another cast in there. This compiles for me (though I haven't actually run it):

    let a1 =
        d.ColumnKeys
        |> Seq.fold 
            (fun acc key -> 
                let values =
                    d 
                    |> Frame.getCol key
                    |> Series.values 
                    |> Seq.map unbox<float>
                values::acc)
            []
        |> Seq.map (fun floats -> floats :> IEnumerable)
        |> Seq.toArray