Java-R-integratie

1. Overzicht

R is een populaire programmeertaal die wordt gebruikt voor statistieken. Omdat het een breed scala aan functies en pakketten beschikbaar heeft, is het niet ongebruikelijk om R-code in andere talen in te sluiten.

In dit artikel zullen we enkele van de meest gebruikelijke manieren bekijken om R-code in Java te integreren.

2. R-script

Voor ons project beginnen we met het implementeren van een heel eenvoudige R-functie die een vector als invoer neemt en het gemiddelde van zijn waarden retourneert. We zullen dit definiëren in een speciaal bestand:

customMean <- functie (vector) {gemiddelde (vector)}

In deze tutorial gebruiken we een Java-helper-methode om dit bestand te lezen en de inhoud ervan als een Draad:

String getMeanScriptContent () gooit IOException, URISyntaxException {URI rScriptUri = RUtils.class.getClassLoader (). GetResource ("script.R"). ToURI (); Pad inputScript = Paths.get (rScriptUri); return Files.lines (inputScript) .collect (Collectors.joining ()); }

Laten we nu eens kijken naar de verschillende opties die we hebben om deze functie vanuit Java aan te roepen.

3. RCaller

De eerste bibliotheek die we gaan overwegen, is RCaller, die code kan uitvoeren door een speciaal R-proces op de lokale computer te starten.

Omdat RCaller beschikbaar is via Maven Central, kunnen we het gewoon opnemen in ons pom.xml:

 com.github.jbytecode RCaller 3.0 

Laten we vervolgens een aangepaste methode schrijven die het gemiddelde van onze waarden retourneert door ons originele R-script te gebruiken:

openbare dubbele gemiddelde (int [] waarden) gooit IOException, URISyntaxException {String fileContent = RUtils.getMeanScriptContent (); RCode-code = RCode.create (); code.addRCode (fileContent); code.addIntArray ("input", waarden); code.addRCode ("result <- customMean (input)"); RCaller-beller = RCaller.create (code, RCallerOptions.create ()); caller.runAndReturnResult ("resultaat"); terug caller.getParser (). getAsDoubleArray ("resultaat") [0]; }

Bij deze methode gebruiken we voornamelijk twee objecten:

  • RCode, die onze codecontext vertegenwoordigt, inclusief onze functie, de invoer en een aanroepinstructie
  • RCaller, waarmee we onze code kunnen uitvoeren en het resultaat kunnen terugkrijgen

Het is belangrijk om dat op te merken RCaller is niet geschikt voor kleine en frequente berekeningen vanwege de tijd die nodig is om het R-proces te starten. Dit is een merkbaar nadeel.

Ook, RCaller werkt alleen als R op de lokale computer is geïnstalleerd.

4. Renjin

Renjin is een andere populaire oplossing die beschikbaar is in het R-integratielandschap. Het wordt op grotere schaal toegepast en biedt ook zakelijke ondersteuning.

Renjin aan ons project toevoegen is iets minder triviaal omdat we de bedatadriven repository samen met de Maven-afhankelijkheid:

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

Laten we nogmaals een Java-wrapper bouwen voor onze R-functie:

openbare dubbele gemiddelde (int [] waarden) gooit IOException, URISyntaxException, ScriptException {RenjinScriptEngine engine = new RenjinScriptEngine (); String meanScriptContent = RUtils.getMeanScriptContent (); engine.put ("input", waarden); engine.eval (meanScriptContent); DoubleArrayVector result = (DoubleArrayVector) engine.eval ("customMean (input)"); return resultaat.asReal (); }

Zoals we kunnen zien, het concept lijkt sterk op RCaller, hoewel het minder uitgebreid is, aangezien we functies direct op naam kunnen aanroepen met behulp van de eval methode.

Het belangrijkste voordeel van Renjin is dat er geen R-installatie nodig is omdat het een op JVM gebaseerde tolk gebruikt. Renjin is momenteel echter niet 100% compatibel met GNU R.

5. Respect

De bibliotheken die we tot nu toe hebben beoordeeld, zijn goede keuzes om lokaal code uit te voeren. Maar wat als we willen dat meerdere clients ons R-script aanroepen? Dat is waar Rserve in het spel komt, waardoor we R-code op een externe machine kunnen uitvoeren via een TCP-server.

Het opzetten van Rserve omvat het installeren van het gerelateerde pakket en het starten van de server met het laden van ons script, via de R-console:

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

Vervolgens kunnen we Rserve nu in ons project opnemen door, zoals gewoonlijk, de Maven-afhankelijkheid toe te voegen:

 org.rosuda.REngine Rserve 1.8.1 

Laten we tot slot ons R-script in een Java-methode verpakken. Hier gebruiken we een RCverbinding object met ons serveradres, standaard 127.0.0.1:6311 indien niet opgegeven:

openbare dubbele gemiddelde (int [] waarden) gooit REngineException, REXPMismatchException {RConnection c = new RConnection (); c.assign ("input", waarden); return c.eval ("customMean (input)"). asDouble (); }

6. FastR

De laatste bibliotheek waar we het over gaan hebben, is FastR. een krachtige R-implementatie gebouwd op GraalVM. Op het moment van schrijven, FastR is alleen beschikbaar op Linux- en Darwin x64-systemen.

Om het te kunnen gebruiken, moeten we GraalVM eerst installeren vanaf de officiële website. Daarna moeten we FastR zelf installeren met behulp van de Graal Component Updater en vervolgens het bijbehorende configuratiescript uitvoeren:

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

Deze keer is onze code afhankelijk van Polyglot, de interne GraalVM API voor het insluiten van verschillende gasttalen in Java. Omdat Polyglot een algemene API is, specificeren we de taal van de code die we willen uitvoeren. We gebruiken ook de c R-functie om onze invoer naar een vector te converteren:

openbare dubbele gemiddelde (int [] waarden) {Context polyglot = Context.newBuilder (). allowAllAccess (true) .build (); String meanScriptContent = RUtils.getMeanScriptContent (); polyglot.eval ("R", meanScriptContent); Waarde rBindings = polyglot.getBindings ("R"); Waarde rInput = rBindings.getMember ("c"). Execute (waarden); retourneer rBindings.getMember ("customMean"). execute (rInput) .asDouble (); }

Houd er bij het volgen van deze aanpak rekening mee dat onze code hierdoor nauw is gekoppeld aan de JVM. Raadpleeg ons artikel over de Graal Java JIT-compiler voor meer informatie over GraalVM.

7. Conclusie

In dit artikel hebben we enkele van de meest populaire technologieën besproken om R in Java te integreren. Opsommen:

  • RCaller is gemakkelijker te integreren omdat het beschikbaar is op Maven Central
  • Renjin biedt bedrijfsondersteuning en vereist niet dat R op de lokale computer wordt geïnstalleerd, maar het is niet 100% compatibel met GNU R
  • Rserve kan worden gebruikt om R-code uit te voeren op een externe server
  • FastR maakt naadloze integratie met Java mogelijk, maar maakt onze code afhankelijk van de VM en is niet voor elk besturingssysteem beschikbaar

Zoals altijd is alle code die in deze tutorial wordt gebruikt, beschikbaar op GitHub.