Подтвердить что ты не робот

Вызов R script из java

Я хотел бы назвать R script с Java. Я выполнил поисковые запросы Google по этой теме, но почти все результаты, которые я видел, потребуют от меня добавления зависимости к какой-либо третьей библиотеке. Может ли кто-нибудь показать мне хороший способ выполнить одно и то же, не добавляя никаких зависимостей от моего кода?

Я использую машину Windows, поэтому, возможно, я могу использовать командную строку для запуска R (если она еще не открыта) и для запуска определенного R script. Но я никогда не писал код командной строки (или называл его с Java), поэтому мне нужны примеры кода.

Я включаю рабочий пример кода, который я написал для одного из возможных подходов ниже, используя мою идею командной строки. В моих комментариях ниже вы можете увидеть, что Шаг третий в AssembleDataFile.java намеренно оставлен пустым мной. Если вы считаете, что можете использовать идею командной строки, то, пожалуйста, покажите мне, какой код писать на третьем шаге.

Кроме того, не стесняйтесь предлагать другой подход, который, надеюсь, не предполагает добавления каких-либо зависимостей к моему коду.

И, как всегда, я очень ценю любые ссылки, которые вы могли бы опубликовать в статьях/учебниках/etc, связанных с этим вопросом.

Вот что я до сих пор:

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 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 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:
Вот сообщение об ошибке, которое возникает при добавлении 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    

ВТОРОЙ РЕДАКТИРОВАНИЕ: Следующий код теперь работает, потому что я следовал за предложениями Винсента. Однако мне пришлось ввести команду сна, чтобы дать R script достаточно времени для запуска. Без команды sleep код java выше вызывает ошибку, указывающую, что файл Matches.csv не существует. Я обеспокоен тем, что 30-секундный период сна является слишком грубым для инструмента. Может ли кто-нибудь показать мне код, который заставляет программу java ждать, пока у программы R есть шанс создать Matches.csv? Я не решаюсь использовать инструменты потоков, потому что я читал, что плохо разработанные потоки могут вызывать ошибки, которые почти невозможно локализовать и исправить.

4b9b3361

Ответ 1

Вы просто хотите вызвать внешнее приложение: не работает ли следующее?

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

Ответ 2

Вы можете легко адаптировать этот код: http://svn.rforge.net/org/trunk/rosuda/REngine/Rserve/test/StartRserve.java

Кроме всего прочего, он находит R и запускает фиксированный script в R - вы можете заменить этот script на ваш script и игнорировать последние два метода.

Ответ 3

Не ждите завершения процесса с помощью 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);
            }

Ответ 4

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

Ответ 5

... потребовал бы, чтобы я добавил зависимость от какой-либо третьей библиотеки...

Почему так плохо? Вы заставляете его звучать так: "... потребовал бы, чтобы я напал на медоносного пена с бейсбольным битом..." Я не вижу вреда, особенно если он работает.

Возможно, RCaller может вам помочь. Не требуется JNI.