Search code examples
c#rcom-interopr.net

R (D)COM how to import c# arrays into R to apply some R algorithms on it


I have read about importing data from a text file into R and processing that data and saving it into a c# variable using R (D)COM. But what i want to do is - import a c# array/list into a r variable and perform the processing on this array.

I've used R.NET with which i could all these but the unresolved bugs like engine.dispose() issue and access violation issue which i get when code is run twice have forced me to search for another interface and i ended up with R (D)COM.

Any help will be appreciated.

Problems using R.NET:(New edit)

I have used R.NET but had stackoverflow error for second run. So used the following piece of code for clearing memory:

engine.Evaluate("rm(gp)");
                        engine.Evaluate("rm(len)");
                        engine.Evaluate("rm(full1)");
                        engine.Evaluate("rm(full)");
                        engine.Evaluate("rm(date)");
                        engine.Evaluate("rm(value)");
                        engine.Evaluate("rm(values)");
                        engine.Evaluate("rm(partial)");
                        engine.Evaluate("rm(modval)");
                        engine.Evaluate("rm(myts)");

                        engine.Evaluate("rm(fit)");
                        engine.Evaluate("rm(h)");
                        engine.Evaluate("rm(test)");
                        engine.Evaluate("rm(testframe)");
                        engine.Evaluate("rm(meanv)");
                        engine.Evaluate("rm(lowv)");
                        engine.Evaluate("rm(highv)");
                        engine.Evaluate("rm(start1)");
                        engine.Evaluate("rm(mod)");
                        engine.Evaluate("gc()");

                        engine.Evaluate("rm( list = ls( all = TRUE ) )");
                        engine.Evaluate("gc()");  

                        GC.Collect();
                        engine.ForceGarbageCollection();

but now i get 'System.AccessViolationException' at the statement

engine.Evaluate("fit<-ets(myts,model=mod,damped=NULL)")

Kindly help me..


Solution

  • I cannot answer regarding R(D)COM, but there is no issue whatsoever with R.NET to do what you describe, so far as I can see. See https://github.com/jmp75/rdotnet-onboarding including a newly added SupportSamples project, reproduced below for information. It ran just fine, on a Linux box at least.

    I suspect you call engine.Dispose() several times. Don't call it until you are really done with all calculations. An R limitation, not an R.NET bug. If you still have an issue, log it as such with reproducible code.

    Hope this helps.

    Code below Worked using:

    • Linux 3.16.0-4-amd64
    • Mono JIT compiler version 3.12.1
    • R version 3.1.2
    • MonoDevelop 5.5
    • R.NET 1.5.19

      static void stackoverflow_27689786_2752565 ()
      {
          REngine.SetEnvironmentVariables();
          REngine engine = REngine.GetInstance();
      
          var rand = new System.Random (0);
          double[] randValues;
      
          for (int i = 0; i < 10; i++) {
              randValues = mkValues (rand, 100);
              Console.WriteLine ("std dev iteration {0} = {1}", i + 1, calcSDev (engine, randValues));
          }
          // you should always dispose of the REngine properly.
          // After disposing of the engine, you cannot reinitialize nor reuse it
          engine.Dispose();
      }
      
      static double[] mkValues (Random rand, int n)
      {
          double[] res = new double[n];
          for (int i = 0; i < n; i++) {
              var v = rand.NextDouble ();
              res [i] = (v < 0 ? -1 : 1) * v * v;
          }
          return res;
      }
      
      static double calcSDev (REngine engine, double[] arr)
      {
          // Note: only one quick and slightly dirty way to do it
          NumericVector rVector = engine.CreateNumericVector(arr);
          engine.SetSymbol ("x", rVector);
          return engine.Evaluate ("sd(x)").AsNumeric () [0];
      }