To Pass Data Between Java and Spotfire Enterprise Runtime for R
TerrJava methods have limitations for evaluating expressions.
One such limitation is that the methods do not support sending data
between Java and
TERR,
except for a single string value returned from
evaluateToString
. Simple values can be included in the
expression string sent to
TERR,
and the string value returned from
evaluateToString
can include some data, but this is not
reasonable for transferring large amounts of data.
The solution is to use methods for converting between TERR data objects and Java TerrData objects:
public static void setVariable(String name, TerrData value)
public static TerrData getVariable(String name)
public static TerrData getVariable(String name, TerrData reuse)
- The first method converts a TerrData object into a TERR data object, and assigns it to the specified global variable.
- The second method retrieves the value of a global variable, and converts it to a TerrData object.
- The third method retrieves a value, but also allows reusing the storage of an existing TerrData object, reducing Java object allocation.
TerrData
is the superclass of several specific classes
for representing particular types of
TERR
data objects, including
TerrDouble
,
TerrString
,
TerrFactor
,
TerrList
, and
TerrDataFrame
. Here is some example code showing how to
start an embedded engine, construct a
TerrDataFrame
object in Java, send it to
TERR,
evaluate a linear model on the data and retrieve the coefficients of the model
as another
TerrData
object.
TerrJava.startEngine();
TerrDataFrame df = new TerrDataFrame(new String[] { "x", "y" },
new TerrData[] {
new TerrDouble(new double[] { 1,2,3,4,5,6 }),
new TerrDouble(new double[] { 1,4,9,16,25,36 })
});
TerrJava.setVariable("df", df);
TerrJava.evaluateInteractive("df.mod <- lm(y~x, data=df)");
TerrJava.evaluateInteractive("df.coef <- df.mod$coefficients");
TerrData coef = TerrJava.getVariable("df.coef");
for (int i=0; i<coef.getLength(); i++) {
System.out.println(coef.names[i]+" : "+((TerrDouble)coef).data[i]);
}
// this prints:
// (Intercept) : -9.333333333333345
// x : 7.000000000000002
Before the development of the
TerrData
object and these methods for reading and
writing variables, the best way to transfer data between Java and
TERR
was to use the
.JavaMethod
function to call static Java methods that
read or write values from static Java fields. However, this only supported
reading and writing simple vectors of doubles, strings, and so on. Large and
complex objects such as
data.frames
could be transferred by breaking them down
into simple vectors that can be transferred via
.JavaMethod
.
This works, but the code is complex and unreliable and slow.
In one test, transferring a data frame with 40 columns of doubles as a
TerrDataFrame
was 100 times as fast as transferring the
columns individually via
.JavaMethod
.