使用 JRI 在 Java 中获得与 R 控制台相同的输出

Get same output as R console in Java using JRI

当我在R控制台中直接输入以下命令时

library("xts")
mySeries <- xts(c(1.0, 2.0, 3.0, 5.0, 6.0), order.by=c(ISOdatetime(2001, 1, 1, 0, 0, 0), ISOdatetime(2001, 1, 2, 0, 0, 0), ISOdatetime(2001, 1, 3, 0, 0, 0), ISOdatetime(2001, 1, 4, 0, 0, 0), ISOdatetime(2001, 1, 5, 0, 0, 0)))
resultingSeries <- to.monthly(mySeries)
resultingSeries 

我会得到这样的输出

             mySeries.Open mySeries.High mySeries.Low mySeries.Close
Jan 2001             1             6            1              6

当我查看属性时,我看到以下输出

attributes(resultingSeries)

$dim
[1] 1 4

$dimnames
$dimnames[[1]]
NULL

$dimnames[[2]]
[1] "mySeries.Open"  "mySeries.High"  "mySeries.Low"   "mySeries.Close"
$index
[1] 978307200
attr(,"tclass")
[1] "yearmon"
$tclass
[1] "POSIXct" "POSIXt" 
$tzone
[1] ""
$class
[1] "xts" "zoo"
$.indexCLASS
[1] "yearmon"

这与我在 Java 中得到的相同。我想知道魔术发生在哪里,以便我看到我在 R 中获得的漂亮输出。我无权访问事件循环,因为我使用的是这样的 JRI(因为,这是推荐的方式并简化了错误处理):

REngine engine = REngine.engineForClass("org.rosuda.REngine.JRI.JRIEngine");
REXP result = engine.parseAndEval(...)

/编辑 在 Java 中,我按如下方式执行上面的每个命令:

REXP result = engine.parseAndEval("resultingSeries") // or any other command

我得到的是

org.rosuda.REngine.REXPDouble@4ac66122+[12]

有效负载加倍:1, 6, 1, 6 属性与上面指定的相同。

现在 R 做了一些魔术来显示上面的输出。有没有一种方法可以获得相同的输出而无需自己手动创建它? R 得到上述输出的实现存储在哪里?

这是一段可以工作的代码,这里我从对象 resultingSeries(我转换为数据框)中提取字段 mySeries.Open 的第一个元素,它等于 1,请注意您不能将所有 resultingSeries 对象 strait 传递到 Java,您需要将其分解。

package Whosebug;

import org.rosuda.JRI.REXP;
import org.rosuda.JRI.Rengine;
/**
 *
 * @author yschellekens
 */
public class Whosebug {      
   public static void main(String[] args) throws Exception {
    String[] Rargs = {"--vanilla"};
    Rengine rengine = new Rengine(  Rargs, false, null);
    rengine.eval("library('xts')");
    rengine.eval("mySeries <- xts(c(1.0, 2.0, 3.0, 5.0, 6.0), order.by=c(ISOdatetime(2001, 1, 1, 0, 0, 0), ISOdatetime(2001, 1, 2, 0, 0, 0), ISOdatetime(2001, 1, 3, 0, 0, 0), ISOdatetime(2001, 1, 4, 0, 0, 0), ISOdatetime(2001, 1, 5, 0, 0, 0)))");
    rengine.eval("resultingSeries <- to.monthly(mySeries)");
    rengine.eval("resultingSeries<-as.data.frame(resultingSeries)");              
    REXP result= rengine.eval("resultingSeries$mySeries.Open");
    System.out.println("Greeting from R: "+result.asDouble());
   }
}

并且 Java 输出:

run:
Greeting from R: 1.0

我找到了以下解决方法。解决方案远非完美。

R 提供了一个命令来将其控制台输出保存为字符向量。

capture.output( {command} )

我们可以使用

访问输出
REXPString s = rengine.parseAndEval("capture.output( to.monthly(mySeries))")
String[] output = result.asStrings()

变量输出将包含所有输出行

[0]             mySeries.Open mySeries.High mySeries.Low mySeries.Close
[1]Jan 2001             1             6            1              6

或者,您可以使用 JRIEngine 并将自己攻击到事件循环,这在我的情况下是不需要的(由于更复杂的错误处理)。