比较java调用R的方法,确定最终合适的方式;重点关注稳定性、对可视化图像(plot,ggplot2)的支持和效率;
已知的方式有:
1:rJava :https://cran.r-project.org/web/packages/rJava/index.html
2:Rserve: http://www.rforge.net/Rserve/
3:Renjin: http://www.renjin.org/
对于Rserve方式有两种客户端连接方式,哪种更好
Rconnection 和Rsession :https://github.com/yannrichet/rsession;
1.rJava
资料地址:https://cran.r-project.org/web/packages/rJava/index.html
1.1 安装:
install.packages("rJava")
1.2 配置
环境变量
CLASSPARH增加:D:\Program Files\R\R-3.4.1\library\rJava\jri\JRI.jar (本地的R安装目录)
PATH增加:D:\Program Files\R\R-3.4.1\bin\x64;D:\Program Files\R\R-3.4.1\library\rJava\jri(本地的R安装目录)
idea中增加: Run-Edit Configurations-VM options ->
-Djava.library.path="D:\Program Files\R\R-3.4.1\library\rJava\jri\x64"(本地的R安装目录)
2.Rserve
资料地址:http://www.rforge.net/Rserve/
对于Rserve方式有两种客户端连接方式:
RConnection :Rserve是一个基于TCP/IP协议的,允许R语言与其他语言通信的C/S结构的程序,支持C/C++,Java,PHP,Python,Ruby,Nodejs等。 Rserve提供远程连接,认证,文件传输等功能。我们可以设计R做为后台服务,处理统计建模,数据分析,绘图等的任务。
Rsession:Rsession提供了一种简单的方式,让Java可以访问远程或本地的Rserve实例。Rsession是对Rserve的封装,提供了更高层的API接口,包括Rserve服务器控制,多会话机制,并支持Windows环境。
2.1 安装:
install.packages('Rserve')
2.2 在程序中,启动Rserve服务器:
library(Rserve)
Rserve()
2.3 在工程中添加Rserve依赖
<dependency>
<groupId>org.rosuda.REngine</groupId>
<artifactId>REngine</artifactId>
<version>2.1.0</version>
</dependency>
<dependency>
<groupId>org.rosuda.REngine</groupId>
<artifactId>Rserve</artifactId>
<version>1.8.1</version>
</dependency>
2.4 在工程中添加Rsession依赖
<dependency>
<groupId>com.github.yannrichet</groupId>
<artifactId>Rsession</artifactId>
<version>1.8.3</version>
</dependency>
3. Renjin
资料地址: http://www.renjin.org/
3.1 下载后启动
java -jar renjin-studio-0.8.2413-jar-with-dependencies.jar
3.2 在工程中添加依赖
<dependency>
<groupId>org.renjin</groupId>
<artifactId>renjin-script-engine</artifactId>
<version>0.8.2413</version>
</dependency>
4. 分别测试把plot图片保存到本地文件
4.1 rJava保存plot图片
public void plot(Rengine re){
re.eval("library(leaps)");
re.eval("states <- as.data.frame(state.x77[, c(\"Murder\", \"Population\",\"Illiteracy\", \"Income\", \"Frost\")])");
re.eval("leaps <- regsubsets(Murder~Population+Illiteracy+Income+Frost,data=states,nbest=4) ");
//保存为图像文件
File tempFile = null;
try {
tempFile = File.createTempFile("rjava-3", ".jpg");
String filePath = tempFile.getAbsolutePath();
re.eval("jpeg('./output/rjava-3.jpg')");
re.eval("plot(leaps,scale = \"adjr2\")");
re.eval("dev.off()");
} catch (IOException e) {
e.printStackTrace();
} finally {
re.end();
}
}
4.2 Rserve保存plot图片
public void plot() throws RserveException, REXPMismatchException, IOException {
RConnection re = new RConnection("localhost");
REXP x = re.eval("R.version.string");
System.out.println(x.asString());
re.eval("library(leaps)");
re.eval("states <- as.data.frame(state.x77[, c(\"Murder\", \"Population\",\"Illiteracy\", \"Income\", \"Frost\")])");
re.eval("leaps <- regsubsets(Murder~Population+Illiteracy+Income+Frost,data=states,nbest=4) ");
//保存为图像文件
File tempFile = null;
try {
tempFile = File.createTempFile("rserve-3", ".jpg");
String filePath = tempFile.getAbsolutePath();
re.eval("jpeg('d://rserve-3.jpg')");
re.eval("plot(leaps,scale = \"adjr2\")");
re.eval("dev.off()");
} catch (IOException e) {
e.printStackTrace();
} catch (REngineException e) {
e.printStackTrace();
}
re.close();
}
4.3 Rsession保存plot图片
public void plot(){
RserverConf rconf = new RserverConf("localhost", 6311, "conan", "conan", new Properties());
Rsession re = Rsession.newInstanceTry(System.out,rconf);
re.eval("library(leaps)");
re.eval("states <- as.data.frame(state.x77[, c(\"Murder\", \"Population\",\"Illiteracy\", \"Income\", \"Frost\")])");
re.eval("leaps <- regsubsets(Murder~Population+Illiteracy+Income+Frost,data=states,nbest=4) ");
re.eval("getwd()");
re.toJPEG(new File("./output/rsession-3.png"), 400, 400, "print(plot(leaps,scale = \"adjr2\"))");
re.end();
}
5.保存ggplot的结果图片
注:需要加上print方法,否则会是空白的。
Rsession:
re.toJPEG(new File("./output/rsession-1.png"), 400, 400, "print(ggplot(data=mpg,aes(x=displ,y=hwy,colour=factor(cyl)))+ geom_point() + geom_smooth())");
Rserve:
re.eval("print(ggplot(plot.data, aes(x=x,y=p,color=factor(delall$delevery_Type)))+geom_point()+ggtitle(\"对分娩方式的预测概率结果与其真实类别图\")+labs(x=\"观测点\",y=\"预测概率\",color=\"实际分娩方式\")+\n" +
" guides(color=guide_legend(title=\"实际分娩方式\",title.theme = element_text(size = 15,face = \"bold\",colour = \"red\",angle = 0)))+mytheme)");
rJava:
re.eval("print(ggplot(data=mpg,aes(x=displ,y=hwy,colour=factor(cyl)))+ geom_point() + geom_smooth())");
6. 对比和选型
通过下面表格中列举的详细信息,结合我们项目的实际需求,最终确定使用Rserve-Rsession。
原因:rJava需要R环境和Java运行环境绑定在一起,所以不考虑了
Renjin不依赖R环境,但是提供的R外部包有限,而且目前不支持画图,所以不考虑
Rsession是Rserve的上层封装,提供更高层的API,使用更友好
名称 | rJava | Rserve- | Rserve- | Renjin |
---|---|---|---|---|
安装 | JDK 配置环境变量 | install.packages("Rserve") library(Rserve) Rserve() | install.packages("Rserve") library(Rserve) Rserve() | |
依赖包 | JRI.jar | REngine.jar Rserve.jar | Rsession.jar REngine.jar, Rserve.jar | renjin-script-engine.jar |
原理 | rJava是一个R语言和Java语言的通信接口,通过底层JNI实现调用,允许在R中直接调用Java的对象和方法。rJava还提供了Java调用R的功能,是通过JRI(Java/R Interface)实现的。JRI现在已经被嵌入到rJava的包中,我们也可以单独使用这个功能。现在rJava包,已经成为很多基于Java开发R包的基础功能组件。 | Rserve是客户端和服务端模式,需要启动Rserve服务,然后客户端通过TCP/IP来与之通信。 基于TCP/IP协议实现与多语言之间的通信,允许R语言与其他语言通信的C/S结构的程序,支持C/C++,Java,PHP,Python,Ruby,Nodejs等 | Rsession是对Rserve的封装,提供了更高层的API接口,包括Rserve服务器控制,多会话机制,并支持Windows环境。 | Renjin是基于JVM的接口,可以在Java中执行R的代码,也可以在R中执行Java的代码。 当使用Renjin Script Engine时, R包完全就像Java和Scala依赖包一样,必须通过Maven或其他build工具,把R依赖包放到classpath中 |
网上的选择意见 | rJava提供一种底层的或者说系统级别的与R的通信机制。 如果你需要嵌入基本R代码片段在java代码,就使用rJava | 如果你需要创建一个R服务器接受来自Java的请求,以及把结果返回java,就是用Rserve | 对比Rserve的JavaAPI,感觉Rsession更友好。这样就能在不打开R编译器的情况下,使用R的底层包服务。更适合于封装R。 | http://packages.renjin.org. |
缺点 | 代码运行环境需要和R在同台机器,包括JDK环境 不同系统的配置方法不一样,Windows和Linux配置方法不同 rJava是通过JNI(Java Native Interface)实现R与Java通信,因此R与Java的执行环境需要在同一台机器上同时存在。 不支持多会话机制 | 需要在R中启动Rserve服务,可以在代码中启动Rserve服务了 | 需要在R中启动Rserve服务,可以在代码中启动Rserve服务了 | 目前不支持plot和ggplot等画图操作,支持的R包有限 |
优点 | rJava可以当作API来使用。不涉及任何客户端-服务端的通信。直接通过rJava执行R代码。 由于rJava是底层接口,并使用JNI作为接口调用,所以效率非常高。在JRI的方案中,JVM直接通过内存直接加载RVM,调用过程性能几乎无损耗,因此是非常高效连接通道,是R和Java通信的首选开发包。 | 与rJava 相比,Rserve 具分散式和低耦合的优势。 Rserve提供远程连接,认证,文件传输等功能。我们可以设计R做为后台服务,处理统计建模,数据分析,绘图等的任务 有点像JDBC,建立一个connection即可 | Rsession提供了一种简单的方式,让Java可以访问远程或本地的Rserve实例。Rsession是对Rserve的封装,提供了更高层的API接口,包括Rserve服务器控制,多会话机制,并支持Windows环境。 | 不依赖R环境 |