4

I am using Java/R/Rserve for a project. I am facing the problem of transferring a multi-dimensional array from Java into R workspace for calculation. So far, the assign method of the RConnection object only allows the following to be passed: byte[], double[], int[], REXP, String,and String[].

I sidestepped this by creating a loop in Java, and passed the variables individually. Although this works, it looks ugly and inefficient.

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)");
  }             
}

The document for Rserve on http://www.rforge.net/Rserve/dist/JRclient/JavaDoc/org/rosuda/JRclient/REXP.html seems to be outdated, and the examples for Rserve are rather limited. Could anyone give me a suggestion on how to improve on this code?

Thank you

1
  • how big is your data? although, I am not sure about the possible precision loss, one way would be to dump your data into strings row by row and call eval with rbind in R, another way - is to dump all your Java data into the file and do read.table in R. Commented Oct 27, 2012 at 6:26

4 Answers 4

2

I found one solution and just made it a little bit more friendly, link on source also attached.

Comments: it's ready-to-use utility method. It based on JRI, which now is a part of rJava.

Source:
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;
    }
Sign up to request clarification or add additional context in comments.

Comments

2

For reference (method might not have been available yet at the time question was asked):

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

Comments

1

what if you do something like this (altering row and line numbers for your needs)?

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());

this returns 10, as expected, but, however, this

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

doesnt printout what it suppose, it just returns 3, maybe my Ubuntu-installed RServe is broken and can't print whatever is after space in result string 3 7:

> rowSums(d)
c1 c2 
3  7 

and I cant find good examples too :(

2 Comments

This is a correct approach, but I did not want to follow it because I am wary of the potential run time/memory cost when using rbind. That's why I allocated the matrix in R at the beginning.
soory, i've posted a wrong timing in the comment, so cleaned that up. My simple wall-time benchmark code is here, seems like rbind is way faster than matrix. i don't know why.
0

You could:

  • flatten the array into a vector of integer rows, such that

    a11 a12

    a21 a22

=>

flat_array = new int[] {a11, a12, a21, a22}
  • Assign that to a local variable e.g:

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

  • Call an R function that makes a matrix (or dataframe) in a global, like:

In R:

 make.matrix <- function(nrows, ncols, values) {

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

In Java:

rEngine.eval("make.matrix(2,2,.values)");
  • Now you have the matrix in temp.res

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.