2012-01-13 67 views
12

Tôi muốn gọi một tập lệnh R từ Java. Tôi đã thực hiện tìm kiếm google về chủ đề này, nhưng hầu như tất cả các kết quả tôi đã thấy sẽ yêu cầu tôi thêm một phụ thuộc vào một số thư viện của bên thứ ba. Bất cứ ai có thể cho tôi một cách tốt để thực hiện điều tương tự mà không cần thêm bất kỳ phụ thuộc vào mã của tôi?gọi R script từ java

Tôi đang sử dụng máy tính cửa sổ, vì vậy có lẽ tôi có thể sử dụng dòng lệnh để bắt đầu R (nếu nó chưa được mở) và chạy một tập lệnh R cụ thể. Nhưng tôi chưa bao giờ viết mã dòng lệnh (hoặc gọi nó từ Java) vì vậy tôi sẽ cần các ví dụ mã.

Tôi bao gồm mã mẫu làm việc mà tôi đã viết cho một phương pháp có thể có bên dưới, sử dụng ý tưởng dòng lệnh của tôi. Trong nhận xét nội dòng của tôi bên dưới, bạn có thể thấy rằng Bước Ba trong AssembleDataFile.java bị tôi bỏ trống. Nếu bạn nghĩ rằng bạn có thể làm cho ý tưởng dòng lệnh hoạt động, thì hãy cho tôi biết mã nào cần viết trong Bước Ba.

Ngoài ra, vui lòng đề xuất một cách tiếp cận khác, hy vọng, không liên quan đến việc thêm bất kỳ phụ thuộc nào vào mã của tôi.

Và, như thường lệ, tôi đánh giá cao mọi liên kết bạn có thể đăng lên các bài viết/hướng dẫn/v.v. liên quan đến câu hỏi này.

Dưới đây là những gì tôi có cho đến nay:

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) 

EDIT:
Đây là thông báo lỗi đang được ném khi tôi thêm Runtime.getRuntime(). Exec ("Rscript" + rScriptFileName); đến đoạn code trên:

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  

THỨ HAI EDIT: Đoạn mã trên hiện đang làm việc vì tôi theo gợi ý của Vincent. Tuy nhiên, tôi phải đưa vào một lệnh ngủ để cung cấp cho kịch bản R đủ thời gian để chạy. Không có lệnh ngủ, mã java ở trên ném một lỗi nói rằng tệp Matches.csv không tồn tại. Tôi lo ngại rằng khoảng thời gian ngủ 30 giây là quá thô của một nhạc cụ. Có ai có thể cho tôi xem mã để chương trình java đợi cho đến khi chương trình R có cơ hội tạo Matches.csv không? Tôi ngần ngại sử dụng các công cụ luồng vì tôi đã đọc rằng các chủ đề được thiết kế kém có thể gây ra các lỗi gần như không thể bản địa hóa và sửa lỗi.

+2

Về chờ đợi cho công việc để hoàn thành: Bạn có thể theo dõi các quá trình ID để chấm dứt. Bạn cũng có thể bình chọn cho sự tồn tại (hoặc không tồn tại) của một số tệp được tạo đặc biệt. – Iterator

Trả lời

14

Bạn chỉ muốn gọi một ứng dụng bên ngoài: không phải công việc sau đây?

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

Cảm ơn bạn rất nhiều vì đã cố gắng giúp đỡ. 1 cho tôi một ý tưởng được nhắm mục tiêu. Tôi đã chạy mã của bạn và nó đang gửi một thông báo lỗi, mà tôi đã đăng ở trên trong bản chỉnh sửa cho bài đăng gốc của tôi. Tôi cũng đã thêm mã của bạn vào phần mã của bài đăng gốc ở trên, để bạn có thể xem những gì tôi đã làm. Có lẽ tôi không hiểu chính xác. Bạn có thể vui lòng chỉ cho tôi cách sửa mã của tôi để mã hoạt động ở trên không? – CodeMed

+1

Bạn có thể cần đường dẫn đầy đủ của tệp thực thi Rscript. –

+0

Tôi có đường dẫn đầy đủ của myScript.R Tôi đã kiểm tra để đảm bảo điều đó trước khi đăng thông báo lỗi. Bạn có nghĩa là con đường đầy đủ của R? – CodeMed

1

... sẽ yêu cầu tôi để thêm một phụ thuộc vào một số thư viện của bên thứ ba ...

Tại sao là xấu như vậy? Bạn làm cho nó âm thanh như "... sẽ yêu cầu tôi tấn công một honeybadger với một cây gậy bóng chày ..." Tôi không thấy tác hại, đặc biệt là nếu nó hoạt động.

Có thể RCaller có thể giúp bạn. Không cần JNI.

+0

Trong khi liên kết này có thể trả lời câu hỏi, tốt hơn nên bao gồm các phần thiết yếu của câu trả lời ở đây và cung cấp liên kết để tham khảo. Câu trả lời chỉ liên kết có thể trở thành không hợp lệ nếu trang được liên kết thay đổi. – durron597

+0

Xin lỗi, nhưng cái bên dưới tôi cũng bao gồm một liên kết. Vì vậy, một trong những bên dưới đó. Tại sao bạn chỉ cho tôi một bình luận? – duffymo

+0

Tôi đã không đơn bạn ra cho bất cứ điều gì, câu trả lời này đã đưa ra trong hàng đợi xem xét LQP. Tôi đã không downvote bạn. – durron597

5

Bạn có thể dễ dàng thích nghi với mã này: http://svn.rforge.net/org/trunk/rosuda/REngine/Rserve/test/StartRserve.java

Trong số những thứ khác nó tìm thấy R và chạy một kịch bản cố định trong R - bạn có thể thay thế kịch bản với với kịch bản của bạn và bỏ qua hai phương pháp cuối cùng.

+0

Cảm ơn bạn đã đề xuất này và nhận xét của bạn về đề xuất của Vincent. Đề xuất của bạn ở trên bao gồm việc thêm một phụ thuộc vào mã của tôi. Tôi thích thú hơn với lời bình luận mà bạn viết trong lời đề nghị của Vincent. Cám ơn bạn một lần nữa. – CodeMed

+1

Đó không phải là một sự phụ thuộc - đoạn mã trên cho thấy cách để có được vị trí của R trên Windows và cách chạy R ở bất kỳ đâu - đó chỉ là mã thực tế đang làm những gì tôi mô tả trong phần bình luận. Nó không liên quan gì đến Rserve ngoại trừ việc nó là một phần của các ví dụ - đó là lý do tại sao tôi bảo bạn bỏ qua những phương pháp cuối cùng phải làm với Rserve - đó không phải là câu trả lời này. Bạn thay thế "thư viện (Rserve)" bằng mã R của riêng bạn. –

+0

Cảm ơn bạn đã làm rõ. +2 nữa để cố gắng giúp đỡ. Tôi sẽ kiểm tra mã của bạn nhiều hơn vào ngày mai, khi tôi tiếp tục làm việc này. – CodeMed

4

Đừng chờ quá trình kết thúc bằng Thread.sleep() ...

Sử dụng phương thức waitFor() thay thế.

  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); 
      } 
2
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(); 
     } 
+0

Tôi không thể xác minh điều này tại thời điểm này. Nhưng +1 dành thời gian để thêm thông tin chi tiết cho câu hỏi cũ này. – CodeMed

+0

Điều đó đã không làm việc cho tôi, nhưng thay đổi đối số cho 'exec' từ' String [] 'thành' Chuỗi' của biểu mẫu 'C:/Program Files/path/sang/the/Rscript.exe C:/path to các/something.R' đã làm các trick. – Antoine