2016-10-07 60 views
0

執行多[R腳本,我與使用rjava的Rengine.eval()方法的Java內調用[R試驗。只要我遵守單行聲明,我就成功地運行了一個簡單的「hello world」腳本並進行簡單的分析。如何評估/使用rjava

但是,當我嘗試執行多行語句(例​​如分配函數定義)時,我無法找到一致的方式來使其工作。

根據此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; 
    } 
} 
+0

您可以使用分號在一行中運行多個命令R,所以我懷疑它會工作,如果你用';'替換所有的'\ n'並把它全部放在一個長字符串中。 – alistaire

+0

感謝您的評論。不幸的是,執行'engine.eval(「print(\」Hello \「); print(\」World!\「)」);'只打印「Hello」。 – Skifozoa

回答

0

我建議使用Rserve代替rJava。

我在我的工作中實現了這兩個功能,並使用rServe解決了我的問題。

rserve的更多實現在附加的鏈接中。

Integrating R with Java

+0

感謝您的建議。我明確地看到使用rServe而不是rJava的好處。但是,對於這個特定的問題,它比解決問題更能避免問題。必須有一致的方法來評估包含多條語句的腳本,這些語句分佈在多行上,不是嗎? – Skifozoa

0

東西,我湊合着用(但並不是最優雅的解決方案)的時刻如下:

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