Integrazione Java-R

1. Panoramica

R è un popolare linguaggio di programmazione utilizzato per le statistiche. Poiché dispone di un'ampia varietà di funzioni e pacchetti, non è raro incorporare il codice R in altri linguaggi.

In questo articolo, daremo uno sguardo ad alcuni dei modi più comuni per integrare il codice R in Java.

2. Script R

Per il nostro progetto, inizieremo implementando una funzione R molto semplice che prende un vettore come input e restituisce la media dei suoi valori. Lo definiremo in un file dedicato:

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

Durante questo tutorial, utilizzeremo un metodo di supporto Java per leggere questo file e restituirne il contenuto come stringa :

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

Ora, diamo un'occhiata alle diverse opzioni che abbiamo per richiamare questa funzione da Java.

3. RCaller

La prima libreria che prenderemo in considerazione è RCaller che può eseguire codice generando un processo R dedicato sulla macchina locale.

Poiché RCaller è disponibile da Maven Central, possiamo semplicemente includerlo nel nostro pom.xml :

 com.github.jbytecode RCaller 3.0 

Successivamente, scriviamo un metodo personalizzato che restituisca la media dei nostri valori utilizzando il nostro script R originale:

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

In questo metodo utilizziamo principalmente due oggetti:

  • RCode , che rappresenta il nostro contesto di codice, inclusa la nostra funzione, il suo input e un'istruzione di chiamata
  • RCaller , che ci consente di eseguire il nostro codice e recuperare il risultato

È importante notare che RCaller non è adatto per calcoli piccoli e frequenti a causa del tempo necessario per avviare il processo R. Questo è un notevole inconveniente.

Inoltre, RCaller funziona solo con R installato sulla macchina locale .

4. Renjin

Renjin è un'altra popolare soluzione disponibile nel panorama di integrazione R. È più ampiamente adottato e offre anche supporto aziendale .

Aggiungere Renjin al nostro progetto è un po 'meno banale poiché dobbiamo aggiungere il repository bedatadriven insieme alla dipendenza Maven:

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

Ancora una volta, costruiamo un wrapper Java per la nostra funzione R:

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

Come possiamo vedere, il concetto è molto simile a RCaller, sebbene sia meno prolisso , poiché possiamo invocare le funzioni direttamente per nome usando il metodo eval .

Il vantaggio principale di Renjin è che non richiede un'installazione R poiché utilizza un interprete basato su JVM. Tuttavia, Renjin non è attualmente compatibile al 100% con GNU R.

5. Rserve

Le librerie che abbiamo esaminato finora sono buone scelte per eseguire codice localmente. Ma cosa succede se vogliamo avere più client che invocano il nostro script R? È qui che entra in gioco Rserve, che ci consente di eseguire il codice R su una macchina remota tramite un server TCP .

L'impostazione di Rserve prevede l'installazione del relativo pacchetto e l'avvio del server che carica il nostro script, tramite la console R:

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

Successivamente, ora possiamo includere Rserve nel nostro progetto, come al solito, aggiungendo la dipendenza Maven:

 org.rosuda.REngine Rserve 1.8.1 

Infine, avvolgiamo il nostro script R in un metodo Java. Qui useremo un oggetto RConnection con il nostro indirizzo del server, predefinito su 127.0.0.1:6311 se non fornito:

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

6. FastR

L'ultima libreria di cui parleremo è FastR. un'implementazione R ad alte prestazioni basata su GraalVM. Al momento della stesura di questo documento, FastR è disponibile solo su sistemi Linux e Darwin x64 .

Per usarlo, dobbiamo prima installare GraalVM dal sito ufficiale. Dopodiché, dobbiamo installare FastR stesso utilizzando Graal Component Updater e quindi eseguire lo script di configurazione fornito con esso:

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

Questa volta il nostro codice dipenderà da Polyglot, l'API interna di GraalVM per incorporare diversi linguaggi guest in Java. Poiché Polyglot è un'API generale, specifichiamo la lingua del codice che vogliamo eseguire. Inoltre, useremo la funzione c R per convertire il nostro input in un vettore:

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

Quando si segue questo approccio, tenere presente che rende il nostro codice strettamente associato alla JVM . Per saperne di più su GraalVM controlla il nostro articolo sul compilatore Graal Java JIT.

7. Conclusione

In questo articolo, abbiamo esaminato alcune delle tecnologie più popolari per l'integrazione di R in Java. Per riassumere:

  • RCaller è più facile da integrare poiché è disponibile su Maven Central
  • Renjin offre supporto aziendale e non richiede l'installazione di R sulla macchina locale, ma non è compatibile al 100% con GNU R.
  • Rserve può essere utilizzato per eseguire il codice R su un server remoto
  • FastR consente una perfetta integrazione con Java ma rende il nostro codice dipendente dalla VM e non è disponibile per tutti i sistemi operativi

Come sempre, tutto il codice utilizzato in questo tutorial è disponibile su GitHub.