Skip to main content

Interfacing C# .Net and R - Integrating the best of both worlds (Part 2)

This post is a continuation from the previous post (Part I) focusing on interfacing C# with R using the R (D)COM. In this post I am going to enhance my previous exercise by creating a Facade .Net Class which facilitates access to specific functions in R.

Creating the R Facade Class

Creating a Facade Class (or a set of .Net classes) which acts as a .Net wrapper to R functions greatly facilitate the use of R functions and their integration within the .Net programming environment. Below I am showing an excerpt from the class RFacade that I have created in this example.

using System;

using System.Collections.Generic;
using System.Linq;
using System.Text;
using StatConnectorCommonLib;
using STATCONNECTORSRVLib;
using System.Runtime.InteropServices;


namespace R
{


class RFacade : IDisposable
{


     private StatConnector rconn;
     private bool disposed = false;


     public RFacade()
     {
          rconn = new STATCONNECTORSRVLib.StatConnector();
          rconn.Init("R");
     }


     public void Dispose()
     {
          Dispose(true);
          GC.SuppressFinalize(this);
     }


     protected virtual void Dispose(bool disposing)
     {
          if (!disposed)
          {
               if (disposing)
               {
                    if (rconn != null)
                    {
                         Marshal.ReleaseComObject(this.rconn);
                         rconn = null;
                    }
               }
               disposed = true;
          }
     }



.... continued

The RFacade constructor handles the creation of the COM connection and initialisation. As you can notice the above example presents also a slight improvement from the previous post when it comes to closing the connection. The RFacade class implements the IDisposable interface to ensure that all unmanaged resources are released when the wrapper is no longer used.

Setting and Getting Data from R

Although in the previous post I showed examples how this can be done, in this example I am going to provide methods in my RFacade class which further simplify the setting and getting of data from R. The two RFacade methods are show below. The first method, RGetRandomNormalVector, creates a vector on R which in return is populated by R with a set of random numbers from a Standard Normal Distribution. The second method, RSetVector, provides similar functionality but this time the data is provided by the C# front end. These two methods show how vectors can be passed easily back and forth between the two layers.

//Function to create an R vector of name [VectorName] and size [size]
//and generates random numbers from normal distribution


public double[] RGetRandomNormalVector (String VectorName, int size)


{
     String RCommand = VectorName + "<-rnorm(" + size + ")";
     double[] data = (double[])rconn.Evaluate(RCommand);
     return data;
}

//Function to create an R vector of name [VectorName] with specific data [data]

public void RSetVector(String VectorName, double[] data)
{
     int vectorSize = data.Count();
     StringBuilder stringData = new StringBuilder(vectorSize);
     for (int c=0; c<=(vectorSize-1); c++) {
          stringData.Append(data[c]);
          if (c < (vectorSize-1) ) {
               stringData.Append(",");
          }
     }
     String RCommand = VectorName + "<-c(" + stringData + ")";
     rconn.EvaluateNoReturn(RCommand);
}

... continued

Exposing R functions

At this stage we have everything ready to start using some R functions. In this example I am going to provide some simple functions which provide a good indication of how one can extend this functionality.


//Function to Calculate Correlation using R cor function

public double RCorrelate(String var1, String Var2)
{
     String RCommand = "cor(" + var1 + "," + Var2 + ")";
     return (double)rconn.Evaluate(RCommand);
}




//Function to plot a simple XY graph using R graphics
public void RPlot(String var1, String Var2)
{
     String RCommand = "plot(" + var1 + "," + Var2 + ")";
     rconn.EvaluateNoReturn(RCommand.ToString());
}




//Function to Calculate Linear Regression using R lm function
//Returns a double array, [0] intercept [1] gradient
public double[] RLinearRegression(String dependentVar, String independentVar)
{
     String RCommand = "fit <- lm("+ dependentVar + " ~ " + independentVar +")";
     rconn.EvaluateNoReturn(RCommand);
     return (double[])rconn.Evaluate("fit$coefficients");
}

Using R from C# .Net is easier...

Once we have our Facade class and also a set of common functions, making use of R becomes much easier from C#. The exerpt below provides examples of method calls from my main Form which accesses a number of exposed R functions via the RFacade object instance RInstance.

double[] year = new double[] { 2000, 2001, 2002, 2003, 2004 };

double[] rate = new double[] { 9.34, 8.50, 7.62, 6.93, 6.60 };


RInstance.RSetVector("year", year);
RInstance.RSetVector("rate", rate);

double corr = RInstance.RCorrelate("year", "rate");

RInstance.RPlot("year", "rate");

double[] regressionCoeff = RInstance.RLinearRegression("rate", "year");


double[] data = RInstance.RGetRandomNormalVector("mydata", dataSize);

This article is continued in a third and final post Part 3.

Comments

wibeasley said…
This is another way to pass a vector (that's not building a string). This poster created an array with the Array.CreateInstance method. I don't know if there are performance advantages though.

http://joachimvandenbogaert.wordpress.com/2009/02/20/rcom-and-c-safearraytypemismatchexception/
Anonymous said…
Hi, Cool entries.
but i have found some bugs

when i tried to execute this method:
double corr = RInstance.RCorrelate("year", "rate");

i became the error that the vars should not be static.

in this case you have to add rconn.SetSymbol(...) extended

thx
Nam
Anonymous said…
I am getting the error, "The name 'FormatDateRange' does not exist in the current context". Is this function located in the RFacade?
Anonymous said…
That last comment was supposed to be under the 3rd section of this series.
Anonymous said…
Hello Vince,

I load a CVS file in R through C# (using statconn). Then, I can not get the data.frame in c#, I only get a null value.Th code:

R.EvaluateNoReturn("c<-read.csv(file=path,head=FALSE,stringsAsFactors = FALSE,sep=',')");
object[] c = R.Evaluate("c");

If I do this

object[] c2 = R.Evaluate("cierres[2,2]");

then I get the value value.

Can I have some help to get th dataframein c# please?
Thanks in advance

Rubo
Sai Elakiyaa said…
Generally, I don't make comments on sites, however, I need to say that this post really pushed me to do as such thing.
Best JAVA Training in Chennai
JAVA Training
Xplore IT Corp said…
Hey Nice Blog!! Thanks For Sharing!!!Wonderful blog & good post.Its really helpful for me, waiting for a more new post. Keep Blogging!
dot net course training in coimbatore
php training in coimbatore
VINITH said…
Thankyou for this wondrous post, I am glad I observed this website on GOOGLE
Digital Marketing courses in Bangalore
Vicky Ram said…
Thanks For Your valuable posting, it was very informative

opencu
Technology

Popular posts from this blog

Interfacing C# .Net and R - Integrating the best of both worlds

In specific software areas like in quantitative finance or else in other mathematical domains, data centric programming typically requires a good balance between three requirements - (1) a solid platform with rich mathematical/statistical functionality (2) having an easy to use, contemporary, programming environment which permits easy and flexible front end code development and (3) an easy to use interface between the two environments. In this artcile I am going to explain how such a balance can be attained by using two of the best products in their specific worlds - using the rich R library as the mathematical/statistical component but then interfacing with C# for the front end application design. As an interfacing option I banked on using R (D)COM which provides an easy to use interfacing method which keeps you away from spending hours identifying interfacing problems. The software required for this tutorial is the following: 1. R software ( download from here ) 2. R (D)COM Interf

Simple moving average trading strategy using Python

Hi All, I am presenting simple boiler point code that can quickly be applied to test technical indicator strategies using Python. The code: 1. downloads daily stock data from google, 2. calculates the short and long moving averages 3. generates the trading signals 4. calculates the daily returns 5. runs the moving average strategy and calculates the cumulative return 6. plots cumulative return of our simple strategy Here is the code ... enjoy trying it out and extend it as required: import numpy as np import pandas_datareader as datar import datetime import matplotlib.pyplot as plt date_start = datetime.datetime( 2017 , 1 , 1 ) date_end = datetime.datetime( 2017 , 6 , 30 ) data = datar.get_data_google( 'AAPL' , date_start , date_end) short_ma = 5 long_ma = 20 data[ 'short_ma' ] = data[ 'Close' ].rolling(short_ma).mean() data[ 'long_ma' ] = data[ 'Close' ].rolling(long_ma).mean() data[ 'masig' ] = data[ 'short_ma'