CDM
CDM

Reputation: 41

C# - linear regression on deedle Series

I have built a deedle series of type:

Series<DateTime, double>

within a C# solution. I am trying to perform a linear regression (still within this solution) using the R function 'lm' (its syntax is lm(y~x, data) where y is the response and x the predictor)

 public static void performLinearRegression(Series<DateTime, double> series)
 {
 }

I would be grateful if someone could help me doing that - if that's possible! I guess I have to use RProvider.RInterop.callFunc but I haven't managed to do so.

Many thanks.

Upvotes: 0

Views: 729

Answers (2)

CDM
CDM

Reputation: 41

Many thanks Tomas for your help.

So I have implemented the following method in C#.

public static Tuple<double, double, double> performLinearRegression(Series<double, double> series)
{
    REngine.SetEnvironmentVariables();
    REngine engine = REngine.GetInstance();
    engine.Initialize();

    var x = engine.CreateNumericVector(series.Keys);
    var y = engine.CreateNumericVector(series.Values);
    engine.SetSymbol("x", x);
    engine.SetSymbol("y", y);
    var result = engine.Evaluate("lm(y~x)");
    engine.SetSymbol("result", result);

    var coefficients = result.AsList()["coefficients"].AsNumeric().ToList();
    double r2 = engine.Evaluate("summary(result)").AsList()["r.squared"].AsNumeric().ToList()[0];
    double intercept = coefficients[0];
    double slope = coefficients[1];

    return Tuple.Create(intercept, slope, r2);
}

where I only referenced RDotNet.

I have also implemented an F# by simply adding an F# project (FSharpInterop) to my C# solution:

namespace FSharpInterop

open System
open RDotNet
open RProvider
open RProvider.graphics
open RProvider.stats
open System.Linq

module myRProvider =

let performLinearRegression X Y =
let dataset =
    namedParams [
        "Y", box Y;
        "X", box X; ]
    |> R.data_frame
let result = R.lm(formula = "Y~X", data = dataset)
let coefficients = result.AsList().["coefficients"].AsNumeric().ToList()
let r2=R.summary(result).AsList().["r.squared"].AsNumeric().ToList().[0]
let inter=coefficients.[0]
let slope=coefficients.[1]
(inter, slope, r2)

Now, referencing FSharpInterop in my ConsoleApplication, I can do the following:

private static void Main(string[] args)
{
    Series<double, double> series= //get a series

    Tuple<double, double, double> deedleRes = myRProvider.performLinearRegression(series.Keys, series.Values);
    Tuple<double, double, double> rDotNetRes=performLinearRegression(series);
}

I have the feeling it is "quick and dirty" (especially because of the way I format the results into a Tuple while I guess there are better ways to get the results in a .Net type easily thanks to Deedle) but at least it should get me going.

If you have any comments or suggestions, feel free to let me know.

Upvotes: 0

Tomas Petricek
Tomas Petricek

Reputation: 243106

There is an F# example on the R provider page showing how to call the lm function, but this is using the R type provider which is, sadly, not supported by C#. When calling R from C#, you probably do not gain much from referencing the R provider, so you'll need to rewrite the sample directly using R.NET.

There is an example showing how to call lm in How to Use lm function in r.net? This saves the data to disk, but you really just need to create a data frame (like the F# sample does) that the function can access - and creating data frames is covered in Creating a Data.Frame using R.NET.

So, I think if you put those two together, you should be able to do this - Deedle sadly won't help you much here, because the nice R type provider support it has is F#-only.

Upvotes: 1

Related Questions