Java-R-Integration

1. Übersicht

R ist eine beliebte Programmiersprache für Statistiken. Da eine Vielzahl von Funktionen und Paketen verfügbar ist, ist es nicht ungewöhnlich, R-Code in andere Sprachen einzubetten.

In diesem Artikel werden einige der häufigsten Möglichkeiten zur Integration von R-Code in Java vorgestellt.

2. R-Skript

Für unser Projekt implementieren wir zunächst eine sehr einfache R-Funktion, die einen Vektor als Eingabe verwendet und den Mittelwert seiner Werte zurückgibt. Wir werden dies in einer dedizierten Datei definieren:

customMean <- function(vector) { mean(vector) }

In diesem Tutorial verwenden wir eine Java-Hilfsmethode, um diese Datei zu lesen und ihren Inhalt als Zeichenfolge zurückzugeben :

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

Schauen wir uns nun die verschiedenen Optionen an, mit denen wir diese Funktion von Java aus aufrufen können.

3. RCaller

Die erste Bibliothek, die wir in Betracht ziehen werden, ist RCaller, der Code ausführen kann, indem er einen dedizierten R-Prozess auf dem lokalen Computer erzeugt.

Da RCaller bei Maven Central erhältlich ist, können wir es einfach in unsere pom.xml aufnehmen :

 com.github.jbytecode RCaller 3.0 

Als nächstes schreiben wir eine benutzerdefinierte Methode, die den Mittelwert unserer Werte mithilfe unseres ursprünglichen R-Skripts zurückgibt:

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]; }

Bei dieser Methode verwenden wir hauptsächlich zwei Objekte:

  • RCode , der unseren Codekontext darstellt, einschließlich unserer Funktion, seiner Eingabe und einer Aufrufanweisung
  • RCaller , mit dem wir unseren Code ausführen und das Ergebnis zurückerhalten können

Es ist wichtig zu beachten, dass RCaller aufgrund der Zeit, die zum Starten des R-Prozesses benötigt wird, nicht für kleine und häufige Berechnungen geeignet ist. Dies ist ein spürbarer Nachteil.

Außerdem funktioniert RCaller nur mit R, das auf dem lokalen Computer installiert ist .

4. Renjin

Renjin ist eine weitere beliebte Lösung in der R-Integrationslandschaft. Es ist weit verbreitet und bietet auch Unternehmensunterstützung .

Das Hinzufügen von Renjin zu unserem Projekt ist etwas weniger trivial, da wir das bedatadriven Repository zusammen mit der Maven-Abhängigkeit hinzufügen müssen :

  bedatadriven bedatadriven public repo //nexus.bedatadriven.com/content/groups/public/     org.renjin renjin-script-engine RELEASE  

Lassen Sie uns noch einmal einen Java-Wrapper für unsere R-Funktion erstellen:

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

Wie wir sehen können, ist das Konzept RCaller sehr ähnlich, obwohl es weniger ausführlich ist , da wir Funktionen mit der eval- Methode direkt namentlich aufrufen können .

Der Hauptvorteil von Renjin besteht darin, dass keine R-Installation erforderlich ist, da ein JVM-basierter Interpreter verwendet wird. Renjin ist derzeit jedoch nicht 100% kompatibel mit GNU R.

5. Rserve

Die Bibliotheken, die wir bisher überprüft haben, sind eine gute Wahl, um Code lokal auszuführen. Aber was ist, wenn mehrere Clients unser R-Skript aufrufen sollen? Hier kommt Rserve ins Spiel, mit dem wir R-Code auf einem Remotecomputer über einen TCP-Server ausführen können .

Zum Einrichten von Rserve müssen Sie das zugehörige Paket installieren und den Server starten, der unser Skript über die R-Konsole lädt:

> install.packages("Rserve") ... > library("Rserve") > Rserve(args = "--RS-source ~/script.R") Starting Rserve...

Als nächstes können wir Rserve jetzt in unser Projekt aufnehmen, indem wir wie üblich die Maven-Abhängigkeit hinzufügen:

 org.rosuda.REngine Rserve 1.8.1 

Lassen Sie uns abschließend unser R-Skript in eine Java-Methode einbinden. Hier verwenden wir ein RConnection- Objekt mit unserer Serveradresse, standardmäßig 127.0.0.1:6311, falls nicht angegeben:

public double mean(int[] values) throws REngineException, REXPMismatchException { RConnection c = new RConnection(); c.assign("input", values); return c.eval("customMean(input)").asDouble(); }

6. FastR

Die letzte Bibliothek, über die wir sprechen werden, ist FastR. Eine leistungsstarke R-Implementierung, die auf GraalVM basiert. Zum Zeitpunkt dieses Schreibens ist FastR nur auf Linux- und Darwin x64-Systemen verfügbar .

Um es zu verwenden, müssen wir zuerst GraalVM von der offiziellen Website installieren. Danach müssen wir FastR selbst mit dem Graal Component Updater installieren und dann das mitgelieferte Konfigurationsskript ausführen:

$ bin/gu install R ... $ languages/R/bin/configure_fastr

Diesmal hängt unser Code von Polyglot ab, der internen GraalVM-API zum Einbetten verschiedener Gastsprachen in Java. Da Polyglot eine allgemeine API ist, geben wir die Sprache des Codes an, den wir ausführen möchten. Außerdem verwenden wir die Funktion c R, um unsere Eingabe in einen Vektor umzuwandeln:

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

Beachten Sie bei diesem Ansatz, dass unser Code eng mit der JVM verbunden ist . Weitere Informationen zu GraalVM finden Sie in unserem Artikel zum Graal Java JIT Compiler.

7. Fazit

In diesem Artikel haben wir einige der beliebtesten Technologien zur Integration von R in Java vorgestellt. Um zusammenzufassen:

  • RCaller ist einfacher zu integrieren, da es in Maven Central verfügbar ist
  • Renjin bietet Unternehmensunterstützung und erfordert nicht, dass R auf dem lokalen Computer installiert ist, aber es ist nicht 100% kompatibel mit GNU R.
  • Mit Rserve kann R-Code auf einem Remote-Server ausgeführt werden
  • FastR ermöglicht eine nahtlose Integration in Java, macht unseren Code jedoch von der VM abhängig und ist nicht für jedes Betriebssystem verfügbar

Wie immer ist der gesamte in diesem Tutorial verwendete Code auf GitHub verfügbar.