Skip to content

Commit 4a45d8c

Browse files
authored
Merge pull request #9155 from aurasphere/master
[BAEL-3489] Added Java-R integration examples.
2 parents 5eb21c5 + 7d6e096 commit 4a45d8c

11 files changed

Lines changed: 352 additions & 0 deletions

File tree

libraries-data-2/pom.xml

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -128,6 +128,21 @@
128128
<version>${awaitility.version}</version>
129129
<scope>test</scope>
130130
</dependency>
131+
<dependency>
132+
<groupId>org.rosuda.REngine</groupId>
133+
<artifactId>Rserve</artifactId>
134+
<version>${rserve.version}</version>
135+
</dependency>
136+
<dependency>
137+
<groupId>com.github.jbytecode</groupId>
138+
<artifactId>RCaller</artifactId>
139+
<version>${rcaller.version}</version>
140+
</dependency>
141+
<dependency>
142+
<groupId>org.renjin</groupId>
143+
<artifactId>renjin-script-engine</artifactId>
144+
<version>${renjin.version}</version>
145+
</dependency>
131146
</dependencies>
132147

133148
<repositories>
@@ -137,6 +152,13 @@
137152
<url>http://repo.numericalmethod.com/maven/</url>
138153
<layout>default</layout>
139154
</repository>
155+
156+
<!-- Needed for Renjin -->
157+
<repository>
158+
<id>bedatadriven</id>
159+
<name>bedatadriven public repo</name>
160+
<url>https://nexus.bedatadriven.com/content/groups/public/</url>
161+
</repository>
140162
</repositories>
141163

142164
<properties>
@@ -153,6 +175,27 @@
153175
<assertj.version>3.6.2</assertj.version>
154176
<slf4j.version>1.7.25</slf4j.version>
155177
<awaitility.version>3.0.0</awaitility.version>
178+
<renjin.version>RELEASE</renjin.version>
179+
<rcaller.version>3.0</rcaller.version>
180+
<rserve.version>1.8.1</rserve.version>
156181
</properties>
157182

183+
<build>
184+
<plugins>
185+
<plugin>
186+
<groupId>org.apache.maven.plugins</groupId>
187+
<artifactId>maven-compiler-plugin</artifactId>
188+
<configuration>
189+
<!-- Excludes FastR classes from compilations since they require GraalVM -->
190+
<excludes>
191+
<exclude>com/baeldung/r/FastRMean.java</exclude>
192+
</excludes>
193+
<testExcludes>
194+
<exclude>com/baeldung/r/FastRMeanUnitTest.java</exclude>
195+
</testExcludes>
196+
</configuration>
197+
</plugin>
198+
</plugins>
199+
</build>
200+
158201
</project>
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
package com.baeldung.r;
2+
3+
import java.io.IOException;
4+
import java.net.URISyntaxException;
5+
6+
/**
7+
* FastR showcase.
8+
*
9+
* @author Donato Rimenti
10+
*/
11+
public class FastRMean {
12+
13+
/**
14+
* Invokes the customMean R function passing the given values as arguments.
15+
*
16+
* @param values the input to the mean script
17+
* @return the result of the R script
18+
*/
19+
public double mean(int[] values) {
20+
Context polyglot = Context.newBuilder()
21+
.allowAllAccess(true)
22+
.build();
23+
String meanScriptContent = RUtils.getMeanScriptContent();
24+
polyglot.eval("R", meanScriptContent);
25+
Value rBindings = polyglot.getBindings("R");
26+
Value rInput = rBindings.getMember("c")
27+
.execute(values);
28+
return rBindings.getMember("customMean")
29+
.execute(rInput)
30+
.asDouble();
31+
}
32+
33+
}
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
package com.baeldung.r;
2+
3+
import java.io.IOException;
4+
import java.net.URISyntaxException;
5+
6+
import com.github.rcaller.rstuff.RCaller;
7+
import com.github.rcaller.rstuff.RCallerOptions;
8+
import com.github.rcaller.rstuff.RCode;
9+
10+
/**
11+
* RCaller showcase.
12+
*
13+
* @author Donato Rimenti
14+
*/
15+
public class RCallerMean {
16+
17+
/**
18+
* Invokes the customMean R function passing the given values as arguments.
19+
*
20+
* @param values the input to the mean script
21+
* @return the result of the R script
22+
* @throws IOException if any error occurs
23+
* @throws URISyntaxException if any error occurs
24+
*/
25+
public double mean(int[] values) throws IOException, URISyntaxException {
26+
String fileContent = RUtils.getMeanScriptContent();
27+
RCode code = RCode.create();
28+
code.addRCode(fileContent);
29+
code.addIntArray("input", values);
30+
code.addRCode("result <- customMean(input)");
31+
RCaller caller = RCaller.create(code, RCallerOptions.create());
32+
caller.runAndReturnResult("result");
33+
return caller.getParser()
34+
.getAsDoubleArray("result")[0];
35+
}
36+
37+
}
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
package com.baeldung.r;
2+
3+
import java.io.IOException;
4+
import java.net.URI;
5+
import java.net.URISyntaxException;
6+
import java.nio.file.Files;
7+
import java.nio.file.Path;
8+
import java.nio.file.Paths;
9+
import java.util.stream.Collectors;
10+
11+
/**
12+
* Utility class for loading the script.R content.
13+
*
14+
* @author Donato Rimenti
15+
*/
16+
public class RUtils {
17+
18+
/**
19+
* Loads the script.R and returns its content as a string.
20+
*
21+
* @return the script.R content as a string
22+
* @throws IOException if any error occurs
23+
* @throws URISyntaxException if any error occurs
24+
*/
25+
static String getMeanScriptContent() throws IOException, URISyntaxException {
26+
URI rScriptUri = RUtils.class.getClassLoader()
27+
.getResource("script.R")
28+
.toURI();
29+
Path inputScript = Paths.get(rScriptUri);
30+
return Files.lines(inputScript)
31+
.collect(Collectors.joining());
32+
}
33+
}
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
package com.baeldung.r;
2+
3+
import java.io.IOException;
4+
import java.net.URISyntaxException;
5+
6+
import javax.script.ScriptException;
7+
8+
import org.renjin.script.RenjinScriptEngine;
9+
import org.renjin.sexp.DoubleArrayVector;
10+
11+
/**
12+
* Renjin showcase.
13+
*
14+
* @author Donato Rimenti
15+
*/
16+
public class RenjinMean {
17+
18+
/**
19+
* Invokes the customMean R function passing the given values as arguments.
20+
*
21+
* @param values the input to the mean script
22+
* @return the result of the R script
23+
* @throws IOException if any error occurs
24+
* @throws URISyntaxException if any error occurs
25+
* @throws ScriptException if any error occurs
26+
*/
27+
public double mean(int[] values) throws IOException, URISyntaxException, ScriptException {
28+
RenjinScriptEngine engine = new RenjinScriptEngine();
29+
String meanScriptContent = RUtils.getMeanScriptContent();
30+
engine.put("input", values);
31+
engine.eval(meanScriptContent);
32+
DoubleArrayVector result = (DoubleArrayVector) engine.eval("customMean(input)");
33+
return result.asReal();
34+
}
35+
36+
}
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
package com.baeldung.r;
2+
3+
import org.rosuda.REngine.REXPMismatchException;
4+
import org.rosuda.REngine.REngineException;
5+
import org.rosuda.REngine.Rserve.RConnection;
6+
7+
/**
8+
* Rserve showcase.
9+
*
10+
* @author Donato Rimenti
11+
*/
12+
public class RserveMean {
13+
14+
/**
15+
* Connects to the Rserve istance listening on 127.0.0.1:6311 and invokes the
16+
* customMean R function passing the given values as arguments.
17+
*
18+
* @param values the input to the mean script
19+
* @return the result of the R script
20+
* @throws REngineException if any error occurs
21+
* @throws REXPMismatchException if any error occurs
22+
*/
23+
public double mean(int[] values) throws REngineException, REXPMismatchException {
24+
RConnection c = new RConnection();
25+
c.assign("input", values);
26+
return c.eval("customMean(input)")
27+
.asDouble();
28+
}
29+
30+
}
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
package com.baeldung.r;
2+
3+
import org.junit.Assert;
4+
import org.junit.Ignore;
5+
import org.junit.Test;
6+
7+
/**
8+
* Test for {@link FastRMean}.
9+
*
10+
* @author Donato Rimenti
11+
*/
12+
@Ignore
13+
public class FastRMeanUnitTest {
14+
15+
/**
16+
* Object to test.
17+
*/
18+
private FastRMean fastrMean = new FastRMean();
19+
20+
/**
21+
* Test for {@link FastRMeanUnitTest#mean(int[])}.
22+
*/
23+
@Test
24+
public void givenValues_whenMean_thenCorrect() {
25+
int[] input = { 1, 2, 3, 4, 5 };
26+
double result = fastrMean.mean(input);
27+
Assert.assertEquals(3.0, result, 0.000001);
28+
}
29+
}
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
package com.baeldung.r;
2+
3+
import java.io.IOException;
4+
import java.net.URISyntaxException;
5+
6+
import javax.script.ScriptException;
7+
8+
import org.junit.Assert;
9+
import org.junit.Ignore;
10+
import org.junit.Test;
11+
12+
/**
13+
* Test for {@link RCallerMean}.
14+
*
15+
* @author Donato Rimenti
16+
*/
17+
@Ignore
18+
public class RCallerMeanIntegrationTest {
19+
20+
/**
21+
* Object to test.
22+
*/
23+
private RCallerMean rcallerMean = new RCallerMean();
24+
25+
/**
26+
* Test for {@link RCallerMeanIntegrationTest#mean(int[])}.
27+
*
28+
* @throws ScriptException if an error occurs
29+
* @throws URISyntaxException if an error occurs
30+
*/
31+
@Test
32+
public void givenValues_whenMean_thenCorrect() throws IOException, URISyntaxException {
33+
int[] input = { 1, 2, 3, 4, 5 };
34+
double result = rcallerMean.mean(input);
35+
Assert.assertEquals(3.0, result, 0.000001);
36+
}
37+
}
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
package com.baeldung.r;
2+
3+
import java.io.IOException;
4+
import java.net.URISyntaxException;
5+
6+
import javax.script.ScriptException;
7+
8+
import org.junit.Test;
9+
10+
import org.junit.Assert;
11+
12+
/**
13+
* Test for {@link RenjinMean}.
14+
*
15+
* @author Donato Rimenti
16+
*/
17+
public class RenjinMeanUnitTest {
18+
19+
/**
20+
* Object to test.
21+
*/
22+
private RenjinMean renjinMean = new RenjinMean();
23+
24+
/**
25+
* Test for {@link RenjinMeanUnitTest#mean(int[])}.
26+
*
27+
* @throws ScriptException if an error occurs
28+
* @throws URISyntaxException if an error occurs
29+
* @throws IOException if an error occurs
30+
*/
31+
@Test
32+
public void givenValues_whenMean_thenCorrect() throws IOException, URISyntaxException, ScriptException {
33+
int[] input = { 1, 2, 3, 4, 5 };
34+
double result = renjinMean.mean(input);
35+
Assert.assertEquals(3.0, result, 0.000001);
36+
}
37+
}
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
package com.baeldung.r;
2+
3+
import org.junit.Assert;
4+
import org.junit.Ignore;
5+
import org.junit.Test;
6+
import org.rosuda.REngine.REXPMismatchException;
7+
import org.rosuda.REngine.REngineException;
8+
9+
/**
10+
* Test for {@link RserveMean}.
11+
*
12+
* @author Donato Rimenti
13+
*/
14+
@Ignore
15+
public class RserveMeanIntegrationTest {
16+
17+
/**
18+
* Object to test.
19+
*/
20+
private RserveMean rserveMean = new RserveMean();
21+
22+
/**
23+
* Test for {@link RserveMeanIntegrationTest#mean(int[])}.
24+
*
25+
* @throws REXPMismatchException if an error occurs
26+
* @throws REngineException if an error occurs
27+
*/
28+
@Test
29+
public void givenValues_whenMean_thenCorrect() throws REngineException, REXPMismatchException {
30+
int[] input = { 1, 2, 3, 4, 5 };
31+
double result = rserveMean.mean(input);
32+
Assert.assertEquals(3.0, result, 0.000001);
33+
}
34+
}

0 commit comments

Comments
 (0)