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.