Merge pull request #9155 from aurasphere/master

[BAEL-3489] Added Java-R integration examples.
This commit is contained in:
Jonathan Cook 2020-04-26 11:47:08 +02:00 committed by GitHub
commit 4a45d8c808
11 changed files with 352 additions and 0 deletions

View File

@ -128,6 +128,21 @@
<version>${awaitility.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.rosuda.REngine</groupId>
<artifactId>Rserve</artifactId>
<version>${rserve.version}</version>
</dependency>
<dependency>
<groupId>com.github.jbytecode</groupId>
<artifactId>RCaller</artifactId>
<version>${rcaller.version}</version>
</dependency>
<dependency>
<groupId>org.renjin</groupId>
<artifactId>renjin-script-engine</artifactId>
<version>${renjin.version}</version>
</dependency>
</dependencies>
<repositories>
@ -137,6 +152,13 @@
<url>http://repo.numericalmethod.com/maven/</url>
<layout>default</layout>
</repository>
<!-- Needed for Renjin -->
<repository>
<id>bedatadriven</id>
<name>bedatadriven public repo</name>
<url>https://nexus.bedatadriven.com/content/groups/public/</url>
</repository>
</repositories>
<properties>
@ -153,6 +175,27 @@
<assertj.version>3.6.2</assertj.version>
<slf4j.version>1.7.25</slf4j.version>
<awaitility.version>3.0.0</awaitility.version>
<renjin.version>RELEASE</renjin.version>
<rcaller.version>3.0</rcaller.version>
<rserve.version>1.8.1</rserve.version>
</properties>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<!-- Excludes FastR classes from compilations since they require GraalVM -->
<excludes>
<exclude>com/baeldung/r/FastRMean.java</exclude>
</excludes>
<testExcludes>
<exclude>com/baeldung/r/FastRMeanUnitTest.java</exclude>
</testExcludes>
</configuration>
</plugin>
</plugins>
</build>
</project>

View File

@ -0,0 +1,33 @@
package com.baeldung.r;
import java.io.IOException;
import java.net.URISyntaxException;
/**
* FastR showcase.
*
* @author Donato Rimenti
*/
public class FastRMean {
/**
* Invokes the customMean R function passing the given values as arguments.
*
* @param values the input to the mean script
* @return the result of the R script
*/
public double mean(int[] values) {
Context polyglot = Context.newBuilder()
.allowAllAccess(true)
.build();
String meanScriptContent = RUtils.getMeanScriptContent();
polyglot.eval("R", meanScriptContent);
Value rBindings = polyglot.getBindings("R");
Value rInput = rBindings.getMember("c")
.execute(values);
return rBindings.getMember("customMean")
.execute(rInput)
.asDouble();
}
}

View File

@ -0,0 +1,37 @@
package com.baeldung.r;
import java.io.IOException;
import java.net.URISyntaxException;
import com.github.rcaller.rstuff.RCaller;
import com.github.rcaller.rstuff.RCallerOptions;
import com.github.rcaller.rstuff.RCode;
/**
* RCaller showcase.
*
* @author Donato Rimenti
*/
public class RCallerMean {
/**
* Invokes the customMean R function passing the given values as arguments.
*
* @param values the input to the mean script
* @return the result of the R script
* @throws IOException if any error occurs
* @throws URISyntaxException if any error occurs
*/
public double mean(int[] values) throws IOException, URISyntaxException {
String fileContent = RUtils.getMeanScriptContent();
RCode code = RCode.create();
code.addRCode(fileContent);
code.addIntArray("input", values);
code.addRCode("result <- customMean(input)");
RCaller caller = RCaller.create(code, RCallerOptions.create());
caller.runAndReturnResult("result");
return caller.getParser()
.getAsDoubleArray("result")[0];
}
}

View File

@ -0,0 +1,33 @@
package com.baeldung.r;
import java.io.IOException;
import java.net.URI;
import java.net.URISyntaxException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.stream.Collectors;
/**
* Utility class for loading the script.R content.
*
* @author Donato Rimenti
*/
public class RUtils {
/**
* Loads the script.R and returns its content as a string.
*
* @return the script.R content as a string
* @throws IOException if any error occurs
* @throws URISyntaxException if any error occurs
*/
static String getMeanScriptContent() throws IOException, URISyntaxException {
URI rScriptUri = RUtils.class.getClassLoader()
.getResource("script.R")
.toURI();
Path inputScript = Paths.get(rScriptUri);
return Files.lines(inputScript)
.collect(Collectors.joining());
}
}

View File

@ -0,0 +1,36 @@
package com.baeldung.r;
import java.io.IOException;
import java.net.URISyntaxException;
import javax.script.ScriptException;
import org.renjin.script.RenjinScriptEngine;
import org.renjin.sexp.DoubleArrayVector;
/**
* Renjin showcase.
*
* @author Donato Rimenti
*/
public class RenjinMean {
/**
* Invokes the customMean R function passing the given values as arguments.
*
* @param values the input to the mean script
* @return the result of the R script
* @throws IOException if any error occurs
* @throws URISyntaxException if any error occurs
* @throws ScriptException if any error occurs
*/
public double mean(int[] values) throws IOException, URISyntaxException, ScriptException {
RenjinScriptEngine engine = new RenjinScriptEngine();
String meanScriptContent = RUtils.getMeanScriptContent();
engine.put("input", values);
engine.eval(meanScriptContent);
DoubleArrayVector result = (DoubleArrayVector) engine.eval("customMean(input)");
return result.asReal();
}
}

View File

@ -0,0 +1,30 @@
package com.baeldung.r;
import org.rosuda.REngine.REXPMismatchException;
import org.rosuda.REngine.REngineException;
import org.rosuda.REngine.Rserve.RConnection;
/**
* Rserve showcase.
*
* @author Donato Rimenti
*/
public class RserveMean {
/**
* Connects to the Rserve istance listening on 127.0.0.1:6311 and invokes the
* customMean R function passing the given values as arguments.
*
* @param values the input to the mean script
* @return the result of the R script
* @throws REngineException if any error occurs
* @throws REXPMismatchException if any error occurs
*/
public double mean(int[] values) throws REngineException, REXPMismatchException {
RConnection c = new RConnection();
c.assign("input", values);
return c.eval("customMean(input)")
.asDouble();
}
}

View File

@ -0,0 +1,29 @@
package com.baeldung.r;
import org.junit.Assert;
import org.junit.Ignore;
import org.junit.Test;
/**
* Test for {@link FastRMean}.
*
* @author Donato Rimenti
*/
@Ignore
public class FastRMeanUnitTest {
/**
* Object to test.
*/
private FastRMean fastrMean = new FastRMean();
/**
* Test for {@link FastRMeanUnitTest#mean(int[])}.
*/
@Test
public void givenValues_whenMean_thenCorrect() {
int[] input = { 1, 2, 3, 4, 5 };
double result = fastrMean.mean(input);
Assert.assertEquals(3.0, result, 0.000001);
}
}

View File

@ -0,0 +1,37 @@
package com.baeldung.r;
import java.io.IOException;
import java.net.URISyntaxException;
import javax.script.ScriptException;
import org.junit.Assert;
import org.junit.Ignore;
import org.junit.Test;
/**
* Test for {@link RCallerMean}.
*
* @author Donato Rimenti
*/
@Ignore
public class RCallerMeanIntegrationTest {
/**
* Object to test.
*/
private RCallerMean rcallerMean = new RCallerMean();
/**
* Test for {@link RCallerMeanIntegrationTest#mean(int[])}.
*
* @throws ScriptException if an error occurs
* @throws URISyntaxException if an error occurs
*/
@Test
public void givenValues_whenMean_thenCorrect() throws IOException, URISyntaxException {
int[] input = { 1, 2, 3, 4, 5 };
double result = rcallerMean.mean(input);
Assert.assertEquals(3.0, result, 0.000001);
}
}

View File

@ -0,0 +1,37 @@
package com.baeldung.r;
import java.io.IOException;
import java.net.URISyntaxException;
import javax.script.ScriptException;
import org.junit.Test;
import org.junit.Assert;
/**
* Test for {@link RenjinMean}.
*
* @author Donato Rimenti
*/
public class RenjinMeanUnitTest {
/**
* Object to test.
*/
private RenjinMean renjinMean = new RenjinMean();
/**
* Test for {@link RenjinMeanUnitTest#mean(int[])}.
*
* @throws ScriptException if an error occurs
* @throws URISyntaxException if an error occurs
* @throws IOException if an error occurs
*/
@Test
public void givenValues_whenMean_thenCorrect() throws IOException, URISyntaxException, ScriptException {
int[] input = { 1, 2, 3, 4, 5 };
double result = renjinMean.mean(input);
Assert.assertEquals(3.0, result, 0.000001);
}
}

View File

@ -0,0 +1,34 @@
package com.baeldung.r;
import org.junit.Assert;
import org.junit.Ignore;
import org.junit.Test;
import org.rosuda.REngine.REXPMismatchException;
import org.rosuda.REngine.REngineException;
/**
* Test for {@link RserveMean}.
*
* @author Donato Rimenti
*/
@Ignore
public class RserveMeanIntegrationTest {
/**
* Object to test.
*/
private RserveMean rserveMean = new RserveMean();
/**
* Test for {@link RserveMeanIntegrationTest#mean(int[])}.
*
* @throws REXPMismatchException if an error occurs
* @throws REngineException if an error occurs
*/
@Test
public void givenValues_whenMean_thenCorrect() throws REngineException, REXPMismatchException {
int[] input = { 1, 2, 3, 4, 5 };
double result = rserveMean.mean(input);
Assert.assertEquals(3.0, result, 0.000001);
}
}

View File

@ -0,0 +1,3 @@
customMean <- function(vector) {
mean(vector)
}