Search code examples
rf#type-providers

How to create a dataframe of multiple types with the RTypeProvider


It seems like the RTypeProvider can only handle namedParams of the same type. Is this the case?

For example,

open RDotNet
open RProvider 

type foo = {
    Which: string
    Qty: float option
    }    

let someFoos = [{Which = "that"; Qty = Some 4.0}; {Which = "other"; Qty = Some 2.0}]

let thingForR = 
    namedParams [
        "which", someFoos |> List.map (fun x -> x.Which); 
        "qty", someFoos |> List.map (fun x -> x.Qty);
        ]
    |> R.data_frame

doesn't work as I get an error on the x.Qty saying

This expression was expected to have type 
  string
but here has type
  float option

If I reverse the order in the thingForR let, then I get the opposite error:

let thingForR = 
    namedParams [
        "qty", someFoos |> List.map (fun x -> x.Qty); 
        "which", someFoos |> List.map (fun x -> x.Which);
        ]
    |> R.data_frame

Here, the error on x.Which is

This expression was expected to have type
  float option
but here has type
  string

Can the dictionary in the namedParams not have different types? If so, how can you create a data frame with different types in F# and pass them to R?


Solution

  • You need to box the values inside the dictionary. That way they are all just object. So:

    let thingForR = 
        namedParams [
            "which", box (someFoos |>  List.map (fun x ->  x.Which) ); 
            "qty", box  (someFoos |> List.map (fun x ->   x.Qty) |> List.map (Option.toNullable >> float));
            ]
        |> R.data_frame
    

    gives me:

    val thingForR :
    SymbolicExpression = which qty
    1 that 4
    2 other 2

    Please refer to your previous question on float option to convert the Option list to float list. Also string option if necessary.

    You can go through Deedle (if not for the option values):

    let someFoos' = [{Which = "that"; Qty =  4.0}; {Which = "other"; Qty =  2.0}]
    let df' = someFoos' |> Frame.ofRecords
    df' |> R.data_frame