Executing R script programmatically

后端 未结 5 840
臣服心动
臣服心动 2020-12-09 18:31

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 d

相关标签:
5条回答
  • 2020-12-09 18:45

    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

    0 讨论(0)
  • 2020-12-09 18:48

    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

    0 讨论(0)
  • 2020-12-09 18:51

    I would presume that C# has a function similar to system() which would allow you to call scripts running via Rscript.exe.

    0 讨论(0)
  • 2020-12-09 18:53

    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");
            }
                }
    
    0 讨论(0)
  • 2020-12-09 19:02

    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();

    0 讨论(0)
提交回复
热议问题