我正在尝试使用 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;
}
}
答案 0 :(得分:0)
答案 1 :(得分:0)
目前我所做的事情(但目前不是最优雅的解决方案)如下:
public REXP executeFromFile(Rengine engine, File file) throws Exception {
String fileName = file.getCanonicalPath().replace("\\", "\\\\");
return execute(engine, "source(\""+fileName+"\")");
}