【问题标题】:Assigning an multi-dimensional array from Java to R through Rserve通过 Rserve 将多维数组从 Java 分配给 R
【发布时间】:2012-10-26 14:57:17
【问题描述】:

我正在为一个项目使用 Java/R/Rserve。我面临将多维数组从 Java 传输到 R 工作区进行计算的问题。到目前为止,RConnection 对象的assign 方法只允许传递以下内容:byte[], double[], int[], REXP, String,and String[]

我通过在 Java 中创建一个循环来回避这个问题,并单独传递变量。尽管这可行,但它看起来丑陋且效率低下。

RConnection c = new RConnection();
c.eval("x <- matrix(0,nrow=dimX[1],ncol=dimX[2])");
for (int i = 0; i < dimX[0]; i++){
  c.assign("i",Integer.toString(i+1));
  c.eval("i <- as.numeric(i)");
  for (int j = 0; j < dimX[1]; j++){
    c.assign("j",Integer.toString(j+1));
c.eval("j <- as.numeric(j)");
c.assign("tmp", Double.toString(XOBS[i][j]));
c.eval("x[i,j] <- as.numeric(tmp)");
  }             
}

http://www.rforge.net/Rserve/dist/JRclient/JavaDoc/org/rosuda/JRclient/REXP.html 上的 Rserve 文档似乎已过时,Rserve 的示例相当有限。谁能给我一个关于如何改进这段代码的建议?

谢谢

【问题讨论】:

  • 您的数据有多大?虽然,我不确定可能的精度损失,一种方法是将您的数据逐行转储到字符串中并在 R 中使用rbind 调用eval,另一种方法是将所有Java数据转储到文件中并在 R 中执行 read.table

标签: java r rserve


【解决方案1】:

我找到了一个解决方案,只是让它更友好一点,还附上了源链接。

评论:它是现成的实用方法。它基于 JRI,现在是 rJava 的一部分。

来源:
http://www.lbgi.fr/wikili/index.php/JRI

    /**
     * Creates and assigns a matrix object in R from 2D table of double
     *
     * @param rEngine        the  R instance used
     * @param sourceArray    the 2D table of double
     *                       the matrix must have always the same column number on every row
     * @param nameToAssignOn the R object name
     * @return R matrix instance or null if R return an error
     */
    public static REXP assignAsRMatrix(Rengine rEngine, double[][] sourceArray, String nameToAssignOn) {
        if (sourceArray.length == 0) {
            return null;
        }

        rEngine.assign(nameToAssignOn, sourceArray[0]);
        REXP resultMatrix = rEngine.eval(nameToAssignOn + " <- matrix( " + nameToAssignOn + " ,nr=1)");
        for (int i = 1; i < sourceArray.length; i++) {
            rEngine.assign("temp", sourceArray[i]);
            resultMatrix = rEngine.eval(nameToAssignOn + " <- rbind(" + nameToAssignOn + ",matrix(temp,nr=1))");
        }

        return resultMatrix;
    }

【讨论】:

    【解决方案2】:

    供参考(在提出问题时方法可能尚不可用):

    REXP REXP.createDoubleMatrix(double[][] arg);
    

    【讨论】:

      【解决方案3】:

      如果您这样做(根据需要更改行号和行号)会怎样?

      RConnection c = new RConnection();
      
      double[][] test = { { 1.0D, 2.0D }, { 3.0D, 4.0D } };
      
      c.assign("res", test[0]);
      for (int i = 1; i < 2; i++) {
        c.assign("tmp", test[i]);
        c.eval("res<-rbind(res,tmp)");
      }
      
      REXP x = c.eval("sum(res)");
      System.out.println(x.asString());
      

      这如预期的那样返回 10,但是,这

      String s = c.eval("rowSums(res)").asString();
      System.out.println(s);
      

      没有打印出它的假设,它只是返回3,也许我的Ubuntu安装的RServe坏了,无法打印结果字符串3 7中空格后的任何内容:

      > rowSums(d)
      c1 c2 
      3  7 
      

      我也找不到好的例子:(

      【讨论】:

      • 这是一种正确的方法,但我不想遵循它,因为我担心使用rbind 时可能会产生运行时间/内存成本。这就是我一开始在 R 中分配矩阵的原因。
      • soory,我在评论中发布了错误的时间,所以清理了它。我简单的挂墙时间benchmark code is here,似乎 rbind 比矩阵快得多。我不知道为什么。
      【解决方案4】:

      你可以:

      • 将数组扁平化为整数行向量,这样

        a11 a12

        a21a22

      =>

      flat_array = new int[] {a11, a12, a21, a22}
      
      • 将其分配给局部变量 例如:

        rEngine.assign(".values", flat_array);

      • 调用 R 函数,在全局中生成矩阵(或数据帧),例如:

      在 R 中:

       make.matrix <- function(nrows, ncols, values) {
      
              value_mat <- matrix(values, nrow=nrows, ncol=ncols, byrow=TRUE)
              temp.res <<- res
              res
          }
      

      在 Java 中:

      rEngine.eval("make.matrix(2,2,.values)");
      
      • 现在你在 temp.res 中有了矩阵

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2013-05-18
        • 2015-07-06
        • 1970-01-01
        • 2011-12-24
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2015-11-12
        相关资源
        最近更新 更多