Как оценить / выполнить многострочный R-скрипт с помощью rjava

Я экспериментирую с вызовом R из Java, используя Rengine.eval()метод rjava. Мне удалось запустить простой сценарий «hello world» и выполнить простой анализ, пока я придерживаюсь инструкций одной строки.

Когда я пытаюсь выполнить многострочный оператор (например, назначение определения функции), однако, я не могу найти последовательный способ заставить его работать.

По словам докладчика в этом видео Devoxx: youtube video, (на отметке 36:52) мульти-скрипты могут быть выполнены путем оценки каждой строки отдельно. То есть, если я не пропущу образец кода, который он показывает на слайде в вышеупомянутый момент.

Так как этот подход меня подводит, я написал модульный тест, который не показывает рабочий подход…

Может ли кто-то с большим опытом пролить свет на это? Поведение для каждого testcase включено в комментарии. (блок кода ниже)

Любая помощь очень ценится

КРОНА

Саймон

import org.junit.Test;
import org.rosuda.JRI.RMainLoopCallbacks;
import org.rosuda.JRI.Rengine;

public class RJavaSanityCheck {

    private static Rengine engine;


    @Test
    public void singleStatementMultiLinesMultiEval(){
        Rengine engine = getEngine();
        engine.eval("myfunc <- function(x){");
        engine.eval("z <- x");
        engine.eval("return (x)");
        engine.eval("}");
        engine.eval("print(myfunc(1))");

        //FAIL: Throws two errors:
        //  Error: object 'x' not found
        //  Error in print(myfunc(1)) : could not find function "myfunc"
    }

    @Test
    public void singleStatementMultiLinesSingleEvalWindows(){
        Rengine engine = getEngine();
        engine.eval("myfunc <- function(x){rnz <- xrnreturn(x)rn}rn");
        engine.eval("print(myfunc(1))");
        engine.end();

        //FAIL: Prints nothing and throws an error:
        //  Error in print(myfunc(1)) : could not find function "myfunc"
    }

    @Test
    public void singleStatementMultiLinesSingleEvalLinux(){
        Rengine engine = getEngine();
        engine.eval("myfunc <- function(x){nz <- xnreturn(x)n}");
        engine.eval("print(myfunc(1))");
        engine.end();

        //SUCCESS: Prints 1
    }

    @Test
    public void multiStatementsMultiLineSingleEvalLinux(){
        Rengine engine = getEngine();
        engine.eval("print("Hello")nprint("World!")");
        engine.end();

        //FAIL: Prints "hello" but not "world!"
    }

    @Test
    public void multiStatementsMultiLineSingleEvalWindows(){
        Rengine engine = getEngine();
        engine.eval("print("Hello")rnprint("World!")");
        engine.end();

        //FAIL: Prints nothing
    }

    @Test
    public void MultiStatementsMultiEval(){
        Rengine engine = getEngine();
        engine.eval("print("Hello")");
        engine.eval("print("World!")");
        engine.end();

        //SUCCESS: Prints Hello World!
    }


    private static  Rengine getEngine(){
        if (engine == null){
            if (!Rengine.versionCheck()){
                throw new RuntimeException("Version mismatch!");
            }
            engine = new Rengine(new String[]{"--vanilla"}, false, new RMainLoopCallbacks() {
                @Override
                public void rWriteConsole(Rengine rengine, String s, int i) {
                    System.out.println(s);
                }

                @Override
                public void rBusy(Rengine rengine, int i) {
                    //Not implemented
                }

                @Override
                public String rReadConsole(Rengine rengine, String s, int i) {
                    //Not implemented
                    return null;
                }

                @Override
                public void rShowMessage(Rengine rengine, String s) {
                    System.out.println(s);
                }

                @Override
                public String rChooseFile(Rengine rengine, int i) {
                    //Not implemented
                    return null;
                }

                @Override
                public void rFlushConsole(Rengine rengine) {
                    //Not implemented
                }

                @Override
                public void rSaveHistory(Rengine rengine, String s) {
                    //Not implemented
                }

                @Override
                public void rLoadHistory(Rengine rengine, String s) {
                    //Not implemented
                }
            });
            if (!engine.waitForR()){
                throw new RuntimeException("Loading error!");
            }
        }
        return engine;
    }
}

2 ответа

  1. Я предлагаю использовать Rserve вместо rJava.

    Я реализовал как в своей работе, так и решил свою проблему с помощью rServe.

    Больше реализации rserve находится в ссылке прилагается.

    Интеграция R с Java

  2. Что-то, что я делаю С (но не является самым элегантным решением) на данный момент является следующим:

    public REXP executeFromFile(Rengine engine, File file) throws Exception {
            String fileName = file.getCanonicalPath().replace("\", "\\");
            return execute(engine, "source(\""+fileName+"\")");
    }