R from within Java
What's the best way to call R functionality from within Java?
I'm looking for a quick, easy and reliable way to make standard 2d scatter plots and histograms in R using my Java applications. I was wondering which packages/interfaces that came up in a quick Google search would be most convenient to use.
I look forward to your suggestions!
Solution 1:
Use JRI: http://www.rforge.net/JRI/. It comes bundled with rJava, including some examples of usage.
A very simple example would be like this:
import java.io.*;
import java.awt.Frame;
import java.util.Enumeration;
import org.rosuda.JRI.Rengine;
import org.rosuda.JRI.REXP;
import org.rosuda.JRI.RVector;
import org.rosuda.JRI.RMainLoopCallbacks;
public class rJavaTest {
public static void main(String[] args) {
Rengine re=new Rengine(args, false, new TextConsole());
REXP x;
re.eval("print(1:10/3)");
System.out.println(x=re.eval("iris"));
RVector v = x.asVector();
if (v.getNames()!=null) {
System.out.println("has names:");
for (Enumeration e = v.getNames().elements() ; e.hasMoreElements() ;) {
System.out.println(e.nextElement());
}
}
if (true) {
System.out.println("Now the console is yours ... have fun");
re.startMainLoop();
} else {
re.end();
System.out.println("end");
}
}
}
Solution 2:
There is something new called http://www.renjin.org/
One thing i like it over JRI
is deployment, While jri
required that your application users will download R, renjin
does not, and it uses only the JVM
to run.
Solution 3:
I have found that forking R as a process, attaching to the process's stdin, stdout, and stderr streams, and sending R commands via the input stream to be quite effective. I use the filesystem to communicate between R and my Java process. This way, I can have multiple R processes running from different threads in Java and their environments do not conflict with each other.
Solution 4:
FastR is a GraalVM based implementation of R. Embedding it in a JVM application is as simple as:
Context ctx = Context.newBuilder("R").allowAllAccess(true).build();
ctx.eval("R", "sum").execute(new int[] {1,2,3});
For your concrete example, this example plots a scatter plot using the lattice
R package, but the output is drawn into Graphics2D
object.
Context context = Context.newBuilder("R").allowAllAccess(true).build();
// This R function opens FastR graphics device passing it Graphics2D object,
// then it plots the graph and closes the device
String src =
"library(grid); library(lattice); " +
"function(graphics, width, height, x, y) { " +
" awt(width, height, graphics);" +
" print(xyplot(as.vector(x) ~ as.vector(y)));" +
" dev.off();" +
"}";
Value showPlot = context.eval("R", src);
// Create a BufferedImage to use for the plotting
BufferedImage image = new BufferedImage(WIDTH, HEIGHT, TYPE_INT_RGB);
Graphics2D graphics = (Graphics2D) image.getGraphics();
graphics.setBackground(new Color(255, 255, 255));
graphics.clearRect(0, 0, WIDTH, HEIGHT);
// Invoke R plotting code and pass it graphics object
double[] x = new double[] {1.,2.,3.,4.};
double[] y = new double[] {1.,2.,3.,4.};
showPlot.execute(graphics, WIDTH, HEIGHT, x, y);
There is also an example that shows the plots inside a Swing window.
You can find more details about FastR in this medium post: https://medium.com/graalvm/faster-r-with-fastr-4b8db0e0dceb