Запустить скрипт R с помощью программы JAVA
Я новичок в программировании на R. Я создал простой R-скрипт и пытаюсь запустить его с использованием класса JAVA, но не могу этого сделать.
Я пытался с помощью Rserve, а также rJava. При использовании Rserve выполнение кода остановилось после создания экземпляра "RConnection", тогда как при использовании rJava было выдано исключение "java.lang.UnsatisfiedLinkError: jri.dll: Не удалось найти зависимые библиотеки".
Код класса JAVA приведен ниже:
Для rJava:
import org.rosuda.JRI.Rengine;
public class Temp {
public static void main(String a[]) {
// Create an R vector in the form of a string.
String javaVector = "c(1,2,3,4,5)";
// Start Rengine.
Rengine engine = new Rengine(new String[] { "--no-save" }, false, null);
// The vector that was created in JAVA context is stored in 'rVector' which is a variable in R context.
engine.eval("rVector=" + javaVector);
//Calculate MEAN of vector using R syntax.
engine.eval("meanVal=mean(rVector)");
//Retrieve MEAN value
double mean = engine.eval("meanVal").asDouble();
//Print output values
System.out.println("Mean of given vector is=" + mean);
}
}
Для Rserve:
import org.rosuda.REngine.REXPMismatchException;
import org.rosuda.REngine.Rserve.RConnection;
import org.rosuda.REngine.Rserve.RserveException;
public class Temp {
public static void main(String a[]) {
RConnection connection = null;
System.out.println("line 10");
try {
// Create a connection to Rserve instance running on default port 6311
System.out.println("line 15");
connection = new RConnection();
System.out.println("line 17");
//Note four slashes (\\\\) in the path
connection.eval("source('D:\\\\RExamples\\\\helloworld.R')");
System.out.println("line 19");
int num1=10;
int num2=20;
int sum=connection.eval("myAdd("+num1+","+num2+")").asInteger();
System.out.println("The sum is=" + sum);
} catch (RserveException e) {
e.printStackTrace();
} catch (REXPMismatchException e) {
e.printStackTrace();
}
}
}
Пожалуйста, дайте мне знать, если мой вопрос вам не ясен или вы хотите узнать что-то еще. Заранее спасибо.
3 ответа
Вы просто хотите вызвать внешнее приложение: не будет ли работать следующее?
Runtime.getRuntime().exec("Rscript myScript.R");
Кредит переходит к самому стеку
Есть два разных подхода для соединения Java и R.
Если вы хотите использовать JRI, вы должны запустить вашу Java-программу, используя параметр JVM -Djava.library.path
указывая на папку, содержащую библиотеку JRI.
Например:
$JAVA_HOME/bin/java -Djava.library.path=/app/vendor/R/lib/R/library/rJava/jri/ -jar target/myapp.jar
Если у вас возникли проблемы с поиском каталога установки JRI, попробуйте найти библиотеку JRI SO:
find / -name "libjri.*"
Кроме того, убедитесь, что вы создали R_HOME и LD_LIBRARY_PATH в своей среде:
- R_HOME: указание на локальную установку R (Ej: /Library/Frameworks/R.framework/Resources)
- LD_LIBRARY_PATH: указание на каталог R lib, а также на каталог JRI (EJ: $LD_LIBRARY_PATH:/app/vendor/R/lib/R/lib:/app/vendor/R/lib/R/bin)
С другой стороны, если вы хотите использовать Rserve, вам нужно запустить Rserve в отдельном процессе, а затем создать RConnection из вашего Java-процесса.
Например:
if(LOGGER.isInfoEnabled()) {
LOGGER.info("Starting RServe process...");
}
ProcessBuilder builder = new ProcessBuilder("/bin/sh", "-c", String.format("echo 'library(Rserve);Rserve(FALSE,args=\"--no-save --slave --RS-conf %s\")'|%s --no-save --slave", rserveConf, rexe));
builder.inheritIO();
Process rProcess = builder.start();
if(LOGGER.isInfoEnabled()) {
LOGGER.info("Waiting for Rserve to start...");
}
int execCodeResult = rProcess.waitFor();
if(execCodeResult != SUCCESS_CODE) {
LOGGER.error(String.format("Unexpected error code starting RServe: %d", execCodeResult));
} else {
LOGGER.error("RServe started successfully");
}
if(LOGGER.isInfoEnabled()) {
LOGGER.info("Opening connection to RServe daemon....");
}
REngine engine = new RConnection();
if(LOGGER.isInfoEnabled()) {
LOGGER.info(String.format("Obtaining R server version: %d", ((RConnection)engine).getServerVersion()));
}
//Perform some engine.parseAndEval("....");
rserveConf - это путь к файлу conf Rserv, а rexe - полный путь к исполняемому файлу R.
Например, на моем компьютере MacOS я могу запустить Rserve, выполнив следующую строку:
/bin/sh -c "echo 'library(Rserve);Rserve(FALSE,args=\"--slave --RS-conf /Users/me/Documents/test/rserve.conf\")'|/Library/Frameworks/R.framework/Versions/3.2/Resources/bin/exec/R --no-save --slave"
Эта команда выводит что-то вроде этого:
Starting Rserve:
/Library/Frameworks/R.framework/Resources/bin/R CMD /Library/Frameworks/R.framework/Versions/3.2/Resources/library/Rserve/libs//Rserve --slave
Rserv started in daemon mode.
Обязательно укажите параметр "--slave" при запуске Rserve.
Если вы хотите увидеть больше примеров, у меня есть демонстрационный проект, который использует оба подхода, JRI и RServe, в моем github:
Альтернативой является использование пакета OpenCpu от r. Это очень простой сервер (к сожалению, однопоточный), который получает вызов функции r через http и возвращает результат в качестве ответа.
Я использовал его для взаимодействия с Java.