Integración Java-R

1. Información general

R es un lenguaje de programación popular utilizado para estadísticas. Dado que tiene una amplia variedad de funciones y paquetes disponibles, no es un requisito poco común incrustar código R en otros lenguajes.

En este artículo, veremos algunas de las formas más comunes de integrar código R en Java.

2. Script de R

Para nuestro proyecto, comenzaremos implementando una función R muy simple que toma un vector como entrada y devuelve la media de sus valores. Definiremos esto en un archivo dedicado:

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

A lo largo de este tutorial, usaremos un método auxiliar de Java para leer este archivo y devolver su contenido como una cadena :

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

Ahora, echemos un vistazo a las diferentes opciones que tenemos para invocar esta función desde Java.

3. RCaller

La primera biblioteca que vamos a considerar es RCaller, que puede ejecutar código generando un proceso R dedicado en la máquina local.

Dado que RCaller está disponible en Maven Central, podemos incluirlo en nuestro pom.xml :

 com.github.jbytecode RCaller 3.0 

A continuación, escribamos un método personalizado que devuelva la media de nuestros valores utilizando nuestro script R original:

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

En este método usamos principalmente dos objetos:

  • RCode , que representa nuestro contexto de código, incluida nuestra función, su entrada y una declaración de invocación
  • RCaller , que nos permite ejecutar nuestro código y recuperar el resultado

Es importante notar que RCaller no es adecuado para cálculos pequeños y frecuentes debido al tiempo que lleva iniciar el proceso R. Este es un inconveniente notable.

Además, RCaller solo funciona con R instalado en la máquina local .

4. Renjin

Renjin es otra solución popular disponible en el panorama de la integración de R. Tiene una adopción más amplia y también ofrece soporte empresarial .

Agregar Renjin a nuestro proyecto es un poco menos trivial ya que tenemos que agregar el repositorio bedatadriven junto con la dependencia de Maven:

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

Una vez más, construyamos un contenedor de Java para nuestra función 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(); }

Como podemos ver, el concepto es muy similar a RCaller, aunque menos detallado , ya que podemos invocar funciones directamente por su nombre usando el método eval .

La principal ventaja de Renjin es que no requiere una instalación de R, ya que utiliza un intérprete basado en JVM. Sin embargo, Renjin actualmente no es 100% compatible con GNU R.

5. Rserve

Las bibliotecas que hemos revisado hasta ahora son buenas opciones para ejecutar código localmente. Pero, ¿qué pasa si queremos que varios clientes invoquen nuestro script R? Ahí es donde entra en juego Rserve, permitiéndonos ejecutar código R en una máquina remota a través de un servidor TCP .

Configurar Rserve implica instalar el paquete relacionado e iniciar el servidor cargando nuestro script, a través de la consola de R:

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

A continuación, ahora podemos incluir Rserve en nuestro proyecto, como de costumbre, agregando la dependencia de Maven:

 org.rosuda.REngine Rserve 1.8.1 

Finalmente, envolvemos nuestro script R en un método Java. Aquí usaremos un objeto RConnection con la dirección de nuestro servidor, por defecto 127.0.0.1:6311 si no se proporciona:

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

6. FastR

La última biblioteca de la que vamos a hablar es FastR. una implementación de R de alto rendimiento construida sobre GraalVM. En el momento de escribir este artículo, FastR solo está disponible en sistemas Linux y Darwin x64 .

Para usarlo, primero debemos instalar GraalVM desde el sitio web oficial. Después de eso, necesitamos instalar FastR usando Graal Component Updater y luego ejecutar el script de configuración que viene con él:

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

Esta vez nuestro código dependerá de Polyglot, la API interna de GraalVM para incrustar diferentes lenguajes invitados en Java. Dado que Polyglot es una API general, especificamos el idioma del código que queremos ejecutar. Además, usaremos la función c R para convertir nuestra entrada en un vector:

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

Al seguir este enfoque, tenga en cuenta que hace que nuestro código esté estrechamente acoplado con la JVM . Para obtener más información sobre GraalVM, consulte nuestro artículo sobre el compilador Graal Java JIT.

7. Conclusión

En este artículo, analizamos algunas de las tecnologías más populares para integrar R en Java. Para resumir:

  • RCaller es más fácil de integrar ya que está disponible en Maven Central
  • Renjin ofrece soporte empresarial y no requiere que R esté instalado en la máquina local, pero no es 100% compatible con GNU R
  • Rserve se puede utilizar para ejecutar código R en un servidor remoto
  • FastR permite una integración perfecta con Java, pero hace que nuestro código dependa de la VM y no está disponible para todos los sistemas operativos.

Como siempre, todo el código utilizado en este tutorial está disponible en GitHub.