java - 从 Java 调用 R 脚本

标签 java r command-line io

我想从 Java 调用 R 脚本。我已经对该主题进行了谷歌搜索,但我看到的几乎所有结果都需要我向某些第三方库添加依赖项。任何人都可以告诉我一个好方法来完成同样的事情而不向我的代码添加任何依赖项吗?

我使用的是 Windows 机器,所以也许我可以使用命令行来启动 R(如果它尚未打开)并运行特定的 R 脚本。但我从未编写过命令行代码(或从 Java 中调用它),因此我需要代码示例。

我在下面使用我的命令行想法为一种可能的方法编写了工作示例代码。在我下面的在线评论中,您可以看到我故意将 AssembleDataFile.java 中的第三步 留空。如果你认为你可以使命令行的想法可行,那么请告诉我在第三步中要写什么代码。

此外,请随意提出另一种方法,希望它不涉及向我的代码添加任何更多依赖项。

而且,一如既往,我非常感谢您可能发布的与此问题相关的文章/教程/等的任何链接。

这是我目前所拥有的:

汇编数据文件.java

import java.io.BufferedReader;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import java.io.PrintWriter;

public class AssembleDataFile {
static String delimiter;
static String localPath = "C:\\test\\cr\\";
static String[][] myDataArray;

public static void main(String[] args) {
    String inputPath = localPath+"pd\\";
    String fileName = "MSData.txt";
    delimiter = "\\t";

    // Step One: Import data in two parts
    try {
        // 1A: get length of data file
        BufferedReader br1 = new BufferedReader(new FileReader(inputPath+fileName));
        int numRows = 0;
        int numCols = 0;
        String currentRow;
        while ((currentRow = br1.readLine()) != null) {
            numRows += 1;
            numCols = currentRow.split(delimiter).length;}
        br1.close();
        //1B: populate data into array
        myDataArray = new String[numRows][numCols+1];
        BufferedReader br2 = new BufferedReader(new FileReader(inputPath+fileName));
        String eachRow;
        int rowIdx = 0;
        while ((eachRow = br2.readLine()) != null) {
            String[] splitRow = eachRow.split(delimiter);
            for(int z = 0;z < splitRow.length;z++){myDataArray[rowIdx][z] = splitRow[z];}
            rowIdx += 1;}
        br2.close();

        // Step Two: Write data to csv
        String rPath = localPath+"r\\";
        String sFileName = rPath+"2colData.csv";
        PrintWriter outputWriter = new PrintWriter(sFileName);
        for(int q = 0;q < myDataArray.length; q++){
            outputWriter.println(myDataArray[q][8]+", "+myDataArray[q][9]);
        }
        outputWriter.close();

        //Step Three: Call R script named My_R_Script.R that uses 2ColData.csv as input
        // not sure how to write this code.  Can anyone help me write this part?
        // For what it is worth, one of the R scripts that I intend to call is included below
        //
        //added the following lines here, per Vincent's suggestion:
            String rScriptFileName = rPath+"My_R_Script.R";
        Runtime.getRuntime().exec("mypathto\\R\\bin\\Rscript "+rScriptFileName);
        //
        //

        //Step Four: Import data from R and put it into myDataArray's empty last column
        try {Thread.sleep(30000);}//make this thread sleep for 30 seconds while R creates the needed file
        catch (InterruptedException e) {e.printStackTrace();}
        String matchFileName = rPath+"Matches.csv";
        BufferedReader br3 = new BufferedReader(new FileReader(matchFileName));
        String thisRow;
        int rowIndex = 0;
        while ((thisRow = br3.readLine()) != null) {
            String[] splitRow = thisRow.split(delimiter);
            myDataArray[rowIndex][numCols] = splitRow[0];
            rowIndex += 1;}
        br3.close();

        //Step Five: Check work by printing out one row from myDataArray
        //Note that the printout has one more column than the input file had.
        for(int u = 0;u<=numCols;u++){System.out.println(String.valueOf(myDataArray[1][u]));}
    }
    catch (FileNotFoundException e) {e.printStackTrace();}
    catch (IOException ie){ie.printStackTrace();}
}
}

My_R_Script.R

myCSV <- read.csv(file="2colData.csv",head=TRUE,sep=",")  
pts = SpatialPoints(myCSV)
Codes = readShapeSpatial("mypath/myshapefile.shp")  
write.csv(ZipCodes$F[overlay(pts,Codes)], "Matches.csv", quote=FALSE, row.names=FALSE)

编辑:
这是我添加 Runtime.getRuntime().exec("Rscript "+rScriptFileName) 时抛出的错误消息;到上面的代码:

java.io.IOException: Cannot run program "Rscript": CreateProcess error=2, The system cannot find the file specified
at java.lang.ProcessBuilder.start(Unknown Source)
at java.lang.Runtime.exec(Unknown Source)
at java.lang.Runtime.exec(Unknown Source)
at java.lang.Runtime.exec(Unknown Source)
at AssembleDataFile.main(AssembleDataFile.java:52)
Caused by: java.io.IOException: CreateProcess error=2, The system cannot find the file specified
at java.lang.ProcessImpl.create(Native Method)
at java.lang.ProcessImpl.<init>(Unknown Source)
at java.lang.ProcessImpl.start(Unknown Source)
... 5 more    

第二次编辑: 上面的代码现在可以工作了,因为我听从了 Vincent 的建议。但是,我不得不输入一个 sleep 命令,以便为 R 脚本提供足够的时间来运行。如果没有 sleep 命令,上面的 java 代码会抛出一个错误,指出 Matches.csv 文件不存在。我担心 30 秒的 sleep 时间对乐器来说太粗糙了。 谁能告诉我让 java 程序等待直到 R 程序有机会创建 Matches.csv 的代码?我对使用线程工具犹豫不决,因为我已经读过设计不当的线程会导致几乎无法定位和修复的错误。

最佳答案

您只想调用一个外部应用程序:下面的方法行不通吗?

Runtime.getRuntime().exec("Rscript myScript.R"); 

关于java - 从 Java 调用 R 脚本,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8844451/

相关文章:

r - 如何在R data.table中按组进行子集设置时获取不同行数的切片

r - 创建一个带有循环的矩阵列表并将它们合并到 R 中

浏览器外的 Javascript

java - Spring MVC 自定义格式化程序在测试中工作但在浏览器中失败

java - 在 Mirth 中将 java 对象从 JMS 队列传递到源?

java - Java 12 中缺少集成测试阶段

java - JPA CriteriaQuery - 如何使用 IN 比较运算符

R:以编程方式生成带有上标的绘图 Axis 中断标签

file - 从包含数千个文件的主文件夹创建 A 到 Z 子文件夹

vb.net - 执行 EXE 时隐藏命令提示符