从C#传递参数到R脚本、运行脚本并获取结果

6
我想知道是否有可能在传递值列表的同时运行R脚本,并输出结果值列表回到C#。我看到有人说R.NET很好,但我只看到使用它直接创建值、操纵值、访问值等示例,而我想要做的是运行已经创建的脚本,将数据输入进去处理后返回数据。我也知道我可以使用CSV文件来实现这一点,但重点是我想省略中间环节。
1个回答

5
这个问题已经有5年了,有一些回答可以参考,比如这里。我将用一个非常简单的R脚本来进行说明。
建议从这个链接开始。
在这个简单的例子中,我向R传递了数字3,然后加上5得到结果(8)。 步骤
  1. Create a text file as name.r, with your r code, something like below. I named it as rcodeTest.r

    library(RODBC) # you can write the results to a database by using this library
    args = commandArgs(trailingOnly = TRUE) # allows R to get parameters
    cat(as.numeric(args[1])+5)# converts 3 to a number (numeric)
    

接下来创建一个C#类(可以随意命名,我称其为RScriptRunner),如下所示,也可在这里找到。 这是一个简单的类,只调用一个过程(一个exe文件)。

    using System;
    using System.Collections.Generic;
    using System.Diagnostics;
    using System.IO;
    using System.Linq;
    using System.Web;

    /// <summary>
    /// Summary description for RScriptRunner
    /// </summary>
    public class RScriptRunner
    {
        public RScriptRunner()
        {
            //
            // TODO: Add constructor logic here
            //
        }
        // 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]);
        ///  
        ///   
        /// rCodeFilePath          - File where your R code is located.
        /// rScriptExecutablePath  - Usually only requires "rscript.exe"
        /// args                   - Multiple R args can be seperated by spaces.
        /// Returns                - a string with the R responses.
        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);
            }
        }
    }

然后调用并传递参数,如下:
     result = RScriptRunner.RunFromCmd(path + @"\rcodeTest.r", @"D:\Programms\R-3.3.3\bin\rscript.exe", "3");

rscript.exe位于您的R目录中,path是您的r脚本(rcodeTest.r)的位置。

现在您可以像下面显示的那样将结果8=5+3作为输出结果。 enter image description here


我的 R 脚本返回带有标题和 3 行的数据框。我该如何读取它? - Janatbek Orozaly
1
您在使用数据库方面有任何限制吗?如果没有,创建一个表并将值存储在该表中(R),然后将表名传递给您的脚本(C#)。或者只需使用预定义的表和模式。您可能需要在R中使用RODBC包来实现此操作。 - Mohsen Sichani
我现在有读取权限,但我必须请求写入权限。但是有没有一种方法可以直接读取输出?而不必将其保存在数据库中? 或者将整个表格准备为字符串并作为字符串发送?我很困惑。我还使用plumber创建了一个REST API,它返回了我期望的JSON结果,但它是单线程的,因此一次只允许一个进程。 - Janatbek Orozaly
2
不确定,但猜测最简单的方法是使用数据库或将其写入文件。如果您将输出作为数据帧传递,则需要一个等效于数据帧的数据类型,我认为这种类型不存在(可能被定义为类或https://dev59.com/j2vXa4cB1Zd3GeqPImEM)。另一种方法是将数据帧转换为字符串(如JSON),然后解码它。如果您找到了一种方法,请分享。 - Mohsen Sichani
1
只需从C#创建一个临时文件,将文件名传递给R脚本,写入文件并返回信号字符串,指示文件已创建并已写入。 - Janatbek Orozaly

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接