如何使用rjava评估/执行多行R脚本

时间:2016-10-07 00:01:48

标签: java r rjava

我正在尝试使用 rjava Rengine.eval()方法从 Java 中调用 R 。我成功地运行了一个简单的'#hello world"脚本和运行简单分析,只要我保持单行语句。

当我尝试执行多行语句(例​​如,分配函数定义)时,我找不到一致的方法来使其工作。

根据Devoxx视频中的演示者:youtube video,(在36:52标记处)可以通过分别评估每一行来执行多个脚本。这是除非我错过解释他在上述瞬间在幻灯片中显示的代码示例。

由于这种方法使我失望,我写了一个单元测试,但没有显示出一种工作方法......

任何有经验的人都可以对此有所了解吗?每个测试用例的行为都包含在注释中。 (下面的代码块)

非常感谢任何帮助

KR

西蒙

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){\r\nz <- x\r\nreturn(x)\r\n}\r\n");
        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 <- x\nreturn(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\")\r\nprint(\"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 个答案:

答案 0 :(得分:0)

我建议使用Rserve而不是rJava。

我在我的工作中实现了两个并使用rServe解决了我的问题。

rserve的更多实现在附加的链接中。

Integrating R with Java

答案 1 :(得分:0)

目前我所做的事情(但目前不是最优雅的解决方案)如下:

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