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



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

当我尝试执行一个多行语句(例如分配一个函数定义),然而,我没能找到一个一致的方法来让它工作。

根据这个Devoxx视频:youtube视频中的演示者,(在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){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;
    }
}

我建议用Rserve代替rJava。

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

更多的实现是在附加的链接。

将R与Java集成

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

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

最新更新