从java调用R脚本

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

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

我正在使用我的命令行思路包括我为下面的一种可能方法编写的工作示例代码。 在下面的内联注释中,您可以看到AssembleDataFile.java中的第三步被我故意留空。 如果您认为可以使命令行思想有效,那么请告诉我在第三步中编写的代码。

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

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

这是我到目前为止:

AssembleDataFile.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.(Unknown Source) at java.lang.ProcessImpl.start(Unknown Source) ... 5 more 

第二次编辑:上面的代码现在有效,因为我遵循了Vincent的建议。 但是,我必须输入一个sleep命令才能让R脚本有足够的时间运行。 如果没有sleep命令,上面的java代码会抛出一条错误,指出Matches.csv文件不存在。 我担心30秒的睡眠时间太长了。 任何人都可以向我展示让java程序等到R程序有机会创建Matches.csv的代码吗? 我对使用线程工具犹豫不决,因为我已经读过设计不佳的线程会导致几乎不可能进行本地化和修复的错误。

您只想调用外部应用程序:以下工作不会吗?

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

您可以轻松地修改此代码: http : //svn.rforge.net/org/trunk/rosuda/REngine/Rserve/test/StartRserve.java

除了其他东西,它找到R并在R中运行一个固定的脚本 – 您可以用脚本替换该脚本并忽略最后两个方法。

不要等待进程完成Thread.sleep()

请改用waitFor()方法。

 Process child = Runtime.getRuntime().exec(command, environments, dataDir); int code = child.waitFor(); switch (code) { case 0: //normal termination, everything is fine break; case 1: //Read the error stream then String message = IOUtils.toString(child.getErrorStream()); throw new RExecutionException(message); } 
 BufferedReader reader = null; Process shell = null; try { shell = Runtime.getRuntime().exec(new String[] { "/usr/bin/Rscript", "/media/subin/works/subzworks/RLanguage/config/predict.R" }); reader = new BufferedReader(new InputStreamReader(shell.getInputStream())); String line; while ((line = reader.readLine()) != null) { System.out.println(line); } } catch (IOException e) { e.printStackTrace(); } 

…需要我为某些第三方库添加依赖…

为什么那么糟糕? 你让它听起来像“……需要我用棒球棒袭击一个蜜蜂……”我没有看到这种伤害,特别是如果它起作用的话。

也许RCaller可以帮到你。 不需要JNI。