I have a C# program that generates some R code. Right now I save the script to file and then copy/paste it into the R console. I know there is a COM interface to R, but it doesn't seem to work with the latest version of R (or any version after 2.7.8). Is there some way I can just programmatically execute the R script from C# after saving it to file?
5 Answers
Here is the class I recently wrote for this purpose. You can also pass in and return arguments from C# and R:
/// <summary> /// This class runs R code from a file using the console. /// </summary> public class RScriptRunner { /// <summary> /// Runs an R script from a file using Rscript.exe. /// Example: /// RScriptRunner.RunFromCmd(curDirectory + @"\ImageClustering.r", "rscript.exe", curDirectory.Replace('\\','/')); /// Getting args passed from C# using R: /// args = commandArgs(trailingOnly = TRUE) /// print(args[1]); /// </summary> /// <param name="rCodeFilePath">File where your R code is located.</param> /// <param name="rScriptExecutablePath">Usually only requires "rscript.exe"</param> /// <param name="args">Multiple R args can be seperated by spaces.</param> /// <returns>Returns a string with the R responses.</returns> public static string RunFromCmd(string rCodeFilePath, string rScriptExecutablePath, string args) { string file = rCodeFilePath; string result = string.Empty; try { var info = new ProcessStartInfo(); info.FileName = rScriptExecutablePath; info.WorkingDirectory = Path.GetDirectoryName(rScriptExecutablePath); info.Arguments = rCodeFilePath + " " + args; info.RedirectStandardInput = false; info.RedirectStandardOutput = true; info.UseShellExecute = false; info.CreateNoWindow = true; using (var proc = new Process()) { proc.StartInfo = info; proc.Start(); result = proc.StandardOutput.ReadToEnd(); } return result; } catch (Exception ex) { throw new Exception("R Script failed: " + result, ex); } } }
NOTE: You may want to add the following to you code, if you are interested in cleaning up the process.
proc.CloseMainWindow(); proc.Close();
- Does not work for me, and does not clean up new cmd*.exe instances - see stackoverflow.com/questions/8559956/…CommentedJun 30, 2015 at 14:21
- I use it all the time. You likely have an issue with rScriptExecutablePath (you process may not have access to the full exe path or you need to create an environment variable for Rscript.exe) , the R code you are trying to run (if the R code fails you will see no results or error), or you could be missing Rscript.exe.CommentedJun 30, 2015 at 15:02
To do this in C#
you'll need to use
shell (R CMD BATCH myRprogram.R)
Be sure to wrap your plots like this
pdf(file="myoutput.pdf") plot (x,y) dev.off()
or image wrappers
- Okay, so right now I have: filled.contour(...) savePlot("heatmap1.png", type="png") You're suggesting I change it to: png("heatmap1.png") filled.contour(...) dev.off()CommentedDec 20, 2010 at 1:16
- 1If you have lattice or ggplot2 plots, you will probably need to use print() around plot statements.CommentedDec 20, 2010 at 10:13
Here is a simple way to achieve that,
My Rscript is located at:
C:\Program Files\R\R-3.3.1\bin\RScript.exe
R Code is at :
C:\Users\lenovo\Desktop\R_trial\withoutALL.R
using System; using System.Diagnostics; public partial class Rscript_runner : System.Web.UI.Page { protected void Button1_Click(object sender, EventArgs e) { Process.Start(@"C:\Program Files\R\R-3.3.1\bin\RScript.exe","C:\\Users\\lenovo\\Desktop\\R_trial\\withoutALL.R"); } }
I would presume that C# has a function similar to system()
which would allow you to call scripts running via Rscript.exe
.
- I thought of that, except when I run the script using Rscript, it doesn't save the plots properly. The script creates a collection of heatmaps and saves the plots to different files. When I run Rscript, it just saves the last picture in a pdf file instead of the separate png files I get when executing through the IDE.CommentedDec 20, 2010 at 0:48
- 1That's how R works interactively versus non-interactively. Open devices like
pdf()
orpng()
orjpeg()
or ... explicitly with filename arguments.CommentedDec 20, 2010 at 0:56 - I thought I was doing that: savePlot("heatmap1.png", type="png");CommentedDec 20, 2010 at 1:03
- 1As I said once before, there is a difference between interactive mode (where
savePlot()
has a meaning) and non-interactive mode where you open devices.CommentedDec 20, 2010 at 3:12
Our solution based on this answer on stackoverflow Call R (programming language) from .net
With monor change, we send R code from string and save it to temp file, since user run custom R code when needed.
public static void RunFromCmd(string batch, params string[] args) { // Not required. But our R scripts use allmost all CPU resources if run multiple instances lock (typeof(REngineRunner)) { string file = string.Empty; string result = string.Empty; try { // Save R code to temp file file = TempFileHelper.CreateTmpFile(); using (var streamWriter = new StreamWriter(new FileStream(file, FileMode.Open, FileAccess.Write))) { streamWriter.Write(batch); } // Get path to R var rCore = Registry.LocalMachine.OpenSubKey(@"SOFTWARE\R-core") ?? Registry.CurrentUser.OpenSubKey(@"SOFTWARE\R-core"); var is64Bit = Environment.Is64BitProcess; if (rCore != null) { var r = rCore.OpenSubKey(is64Bit ? "R64" : "R"); var installPath = (string)r.GetValue("InstallPath"); var binPath = Path.Combine(installPath, "bin"); binPath = Path.Combine(binPath, is64Bit ? "x64" : "i386"); binPath = Path.Combine(binPath, "Rscript"); string strCmdLine = @"/c """ + binPath + @""" " + file; if (args.Any()) { strCmdLine += " " + string.Join(" ", args); } var info = new ProcessStartInfo("cmd", strCmdLine); info.RedirectStandardInput = false; info.RedirectStandardOutput = true; info.UseShellExecute = false; info.CreateNoWindow = true; using (var proc = new Process()) { proc.StartInfo = info; proc.Start(); result = proc.StandardOutput.ReadToEnd(); } } else { result += "R-Core not found in registry"; } Console.WriteLine(result); } catch (Exception ex) { throw new Exception("R failed to compute. Output: " + result, ex); } finally { if (!string.IsNullOrWhiteSpace(file)) { TempFileHelper.DeleteTmpFile(file, false); } } } }
Full blog post: http://kostylizm.blogspot.ru/2014/05/run-r-code-from-c-sharp.html