Java-R интеграция

1. Общ преглед

R е популярен език за програмиране, използван за статистика. Тъй като разполага с голямо разнообразие от функции и пакети, не е необичайно изискване за вграждане на R код в други езици.

В тази статия ще разгледаме някои от най-често срещаните начини за интегриране на R кода в Java.

2. R сценарий

За нашия проект ще започнем с прилагане на много проста R функция, която приема вектор като вход и връща средната стойност на неговите стойности. Ще определим това в специален файл:

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

В този урок ще използваме помощен метод на Java, за да прочетем този файл и да върнем съдържанието му като низ :

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

Сега, нека да разгледаме различните опции, които трябва да извикаме тази функция от Java.

3. RCaller

Първата библиотека, която ще разгледаме, е RCaller, която може да изпълнява код, като създава специален R процес на локалната машина.

Тъй като RCaller се предлага от Maven Central, можем просто да го включим в нашия pom.xml :

 com.github.jbytecode RCaller 3.0 

След това нека напишем персонализиран метод, който връща средната стойност на нашите стойности с помощта на оригиналния ни R скрипт:

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

В този метод използваме основно два обекта:

  • RCode , който представлява нашия контекст на кода, включително нашата функция, нейния вход и изявление за извикване
  • RCaller , който ни позволява да стартираме нашия код и да получим резултата обратно

Важно е да се отбележи, че RCaller не е подходящ за малки и чести изчисления поради времето, необходимо за стартиране на R процеса. Това е забележим недостатък.

Също така, RCaller работи само с R, инсталиран на локалната машина .

4. Ренджин

Renjin е друго популярно решение, налично в контекста на R интеграцията. Той е по-широко приет и предлага и корпоративна подкрепа .

Добавянето на Renjin към нашия проект е малко по-малко тривиално, тъй като трябва да добавим хранилището bedatadriven заедно с зависимостта на Maven:

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

Още веднъж, нека да изградим Java обвивка към нашата функция 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(); }

Както виждаме, концепцията е много подобна на RCaller, въпреки че е по-малко подробна , тъй като можем да извикваме функции директно по име, използвайки метода eval .

Основното предимство на Renjin е, че не изисква R инсталация, тъй като използва интерпретатор, базиран на JVM. В момента обаче Renjin не е 100% съвместим с GNU R.

5. Резерв

Библиотеките, които разгледахме досега, са добър избор за локално стартиране на код. Но какво, ако искаме да имаме множество клиенти, които извикват нашия R скрипт? Това е мястото, където Rserve влиза в игра, позволявайки ни да стартираме R код на отдалечена машина чрез TCP сървър .

Настройването на Rserve включва инсталиране на свързания пакет и стартиране на сървъра, зареждащ нашия скрипт, чрез R конзолата:

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

След това вече можем да включим Rserve в нашия проект, както обикновено, добавяйки зависимостта Maven:

 org.rosuda.REngine Rserve 1.8.1 

И накрая, нека увием нашия R скрипт в Java метод. Тук ще използваме обект RConnection с адреса на нашия сървър, който по подразбиране е 127.0.0.1:6311, ако не е предоставен:

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

6. FastR

Последната библиотека, за която ще говорим, е FastR. високоефективно R изпълнение, изградено върху GraalVM. По време на това писане FastR е достъпен само за Linux и Darwin x64 системи .

За да го използваме, първо трябва да инсталираме GraalVM от официалния уебсайт. След това трябва да инсталираме самия FastR с помощта на Graal Component Updater и след това да стартираме конфигурационния скрипт, който идва с него:

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

Този път нашият код ще зависи от Polyglot, вътрешния API на GraalVM за вграждане на различни езици за гости в Java. Тъй като Polyglot е общ API, ние посочваме езика на кода, който искаме да изпълним. Също така ще използваме функцията c R, за да преобразуваме входа си във вектор:

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

Когато следвате този подход, имайте предвид, че той прави нашия код тясно свързан с JVM . За да научите повече за GraalVM, вижте нашата статия за Graal Java JIT Compiler.

7. Заключение

В тази статия разгледахме някои от най-популярните технологии за интегриране на R в Java. Да обобщим:

  • RCaller е по-лесен за интегриране, тъй като е достъпен в Maven Central
  • Renjin предлага корпоративна поддръжка и не изисква R да бъде инсталиран на локалната машина, но не е 100% съвместим с GNU R
  • Rserve може да се използва за изпълнение на R код на отдалечен сървър
  • FastR позволява безпроблемна интеграция с Java, но прави нашия код зависим от виртуалната машина и не е наличен за всяка операционна система

Както винаги, целият код, използван в този урок, е достъпен в GitHub.