R的极客理想系列文章,涵盖了R的思想,使用,工具,创新等的一系列要点,以我个人的学习和体验去诠释R的强大。
R语言作为统计学一门语言,一直在小众领域闪耀着光芒。直到大数据的爆发,R语言变成了一门炙手可热的数据分析的利器。随着越来越多的工程背景的人的加入,R语言的社区在迅速扩大成长。现在已不仅仅是统计领域,教育,银行,电商,互联网….都在使用R语言。
要成为有理想的极客,我们不能停留在语法上,要掌握牢固的数学,概率,统计知识,同时还要有创新精神,把R语言发挥到各个领域。让我们一起动起来吧,开始R的极客理想。
关于作者:
- 张丹(Conan), 程序员Java,R,PHP,Javascript
- weibo:@Conan_Z
- blog: http://blog.fens.me
- email: bsspirit@gmail.com
转载请注明出处:
http://blog.fens.me/r-rjava-java
前言
Java语言在工业界长期处于霸主地位,Java语法、JVM、JDK、Java开源库,在近10年得到了爆发式的发展,几乎覆盖了应用开发的所有领域。伴随着Java的全领域发展,问题也随之而来了。语法越来越复杂,近似的项目越来越多,学好Java变得很难。对于没有IT背景的统计人员,学用Java更是难于上青天。
R一直是统计圈内处于佼佼者的语言,语法简单,学习曲线不太长也不太陡。如果能结合Java的通用性和R的专业性,碰撞出的火花,将会缤纷绚烂。
本文将介绍R与Java连接的高速通道,rJava通信方案。另外一篇文章介绍的Rserve通信方案,请参考: Rserve与Java的跨平台通信
目录
- rJava介绍
- rJava安装
- rJava实现R调用Java
- rJava(JRI)实现Java调用R (win7)
- rJava(JRI)实现Java调用R (Ubuntu)
1. rJava介绍
rJava是一个R语言和Java语言的通信接口,通过底层JNI实现调用,允许在R中直接调用Java的对象和方法。
rJava还提供了Java调用R的功能,是通过JRI(Java/R Interface)实现的。JRI现在已经被嵌入到rJava的包中,我们也可以单独试用这个功能。现在rJava包,已经成为很多基于Java开发R包的基础功能组件。
正式由于rJava是底层接口,并使用JNI作为接口调用,所以效率非常高。在JRI的方案中,JVM直接通过内存直接加载RVM,调用过程性能几乎无损耗,因此是非常高效连接通道,是R和Java通信的首选开发包。
2. rJava安装
系统环境:
- Linux Ubuntu 12.04.2 LTS 64bit server
- R version 3.0.1 64bit
- Java (Oracle SUN) 1.6.0_29 64bit Server VM
~ uname -a
Linux conan 3.5.0-23-generic #35~precise1-Ubuntu SMP Fri Jan 25 17:13:26 UTC 2013 x86_64 x86_64 x86_64 GNU/Linux
~ cat /etc/issue
Ubuntu 12.04.2 LTS \n \l
~ R --version
R version 3.0.1 (2013-05-16) -- "Good Sport"
Copyright (C) 2013 The R Foundation for Statistical Computing
Platform: x86_64-pc-linux-gnu (64-bit)
R is free software and comes with ABSOLUTELY NO WARRANTY.
You are welcome to redistribute it under the terms of the
GNU General Public License versions 2 or 3.
For more information about these matters see
http://www.gnu.org/licenses/.
~ java -version
java version "1.6.0_29"
Java(TM) SE Runtime Environment (build 1.6.0_29-b11)
Java HotSpot(TM) 64-Bit Server VM (build 20.4-b02, mixed mode)
rJava安装
#配置rJava环境
~ sudo R CMD javareconf
#启动R
~ sudo R
> install.packages("rJava")
installing via 'install.libs.R' to /usr/local/lib/R/site-library/rJava
** R
** inst
** preparing package for lazy loading
** help
*** installing help indices
** building package indices
** testing if installed package can be loaded
* DONE (rJava)
The downloaded source packages are in
‘/tmp/RtmpiZyCE7/downloaded_packages’
3. rJava实现R调用Java
在R环境中,使用rJava包编程
#加载rJava包
> library(rJava)
> search()
[1] ".GlobalEnv" "package:rJava" "package:stats"
[4] "package:graphics" "package:grDevices" "package:utils"
[7] "package:datasets" "package:methods" "Autoloads"
[10] "package:base"
#启动JVM
> .jinit()
#声明并赋值到字符串
> s <- .jnew("java/lang/String", "Hello World!")
> s
[1] "Java-Object{Hello World!}"
#查看字符串长度
> .jcall(s,"I","length")
[1] 12
#索引World的位置
> .jcall(s,"I","indexOf","World")
[1] 6
#查看concat的方法声明
> .jmethods(s,"concat")
[1] "public java.lang.String java.lang.String.concat(java.lang.String)"
#使用concat方法连接字符串
> .jcall(s,"Ljava/lang/String;","concat",s)
[1] "Hello World!Hello World!"
#打印字符串对象
> print(s)
[1] "Java-Object{Hello World!}"
#打印字符串值
> .jstrVal(s)
[1] "Hello World!"
rJava优化过的方法调用,用$来调用方法
#同.jcall(s,"I","length")
> s$length()
[1] 12
#同.jcall(s,"I","indexOf","World")
> s$indexOf("World")
[1] 6
4. rJava(JRI)实现Java调用R (win7)
在win7中安装rJava
系统环境:
- win7 64bit 旗舰版
- R 3.0.1
- Java 1.6.0_45
设置环境变量
PATH: C:\Program Files\R\R-3.0.1\bin\x64;D:\toolkit\java\jdk6\bin;;D:\toolkit\java\jdk6\jre\bin\server
JAVA_HOME: D:\toolkit\java\jdk6
CLASSPATH: C:\Program Files\R\R-3.0.1\library\rJava\jri
在R中安装rJava
> install.packages("rJava")
#加载rJava
> library(rJava)
> .jinit()
#R调用Java变量测试
> s <- .jnew("java/lang/String", "Hello World!")
> s
[1] "Java-Object{Hello World!}"
package org.conan.r.rjava;
import org.rosuda.JRI.Rengine;
public class DemoRJava {
public static void main(String[] args) {
DemoRJava demo = new DemoRJava();
demo.callRJava();
}
public void callRJava() {
Rengine re = new Rengine(new String[] { "--vanilla" }, false, null);
if (!re.waitForR()) {
System.out.println("Cannot load R");
return;
}
//打印变量
String version = re.eval("R.version.string").asString();
System.out.println(version);
//循环打印数组
double[] arr = re.eval("rnorm(10)").asDoubleArray();
for (double a : arr) {
System.out.print(a + ",");
}
re.end();
}
}
在Eclipse启动设置VM参数:
-Djava.library.path="C:\Program Files\R\R-3.0.1\library\rJava\jri\x64"
运行结果:
R version 3.0.1 (2013-05-16)
0.04051018703700011,-0.3321596519938258,0.45642459001166913,-1.1907153494936031,1.5872266854172385,1.3639721994863943,-0.6309712627586983,-1.5226698569087498,-1.0416402147174952,0.4864034017637044,
打包DemoRJava.jar
在Eclipse中完成打包,上传到linux环境,继续测试。
5. rJava(JRI)实现Java调用R (Ubuntu)
新建目录DemoRJava,上传DemoRJava.jar到DemoRJava
~ mkdir /home/conan/R/DemoRJava
~ cd /home/conan/R/DemoRJava
~ ls -l
-rw-r--r-- 1 conan conan 1328 Aug 8 2013 DemoRJava.jar
运行Jar包
~ export R_HOME=/usr/lib/R
~ java -Djava.library.path=/usr/local/lib/R/site-library/rJava/jri -cp /usr/local/lib/R/site-library/rJava/jri/JRI.jar:/home/conan/R/DemoRJava/DemoRJava.jar org.conan.r.rjava.DemoRJava
运行结果
R version 3.0.1 (2013-05-16)
0.6374494596732511,1.3413824702002808,0.04573045670001342,-0.6885617932810327,0.14970067632722675,-0.3989493870007832,-0.6148250252955993,0.40132038323714453,-0.5385260423222166,0.3459850956295771,
我们完成了,R和Java的互调。包括了R通过rJava调用Java,Java通过JRI调用R。并演示了win和linux中的使用方法。
转载请注明出处:
http://blog.fens.me/r-rjava-java
我有一个困扰我很久的问题,正好你写了这篇文章,于是向你请教一下:在knitr里面我有一些调用外部语言的方式( http://yihui.name/knitr/demo/engines/ ),对于Java,我想实现类似的功能,就是以字符串的形式给你一段Java代码,在R里面调用Java运行它,然后返回stdout中的输出。这个rJava可以实现吗?
可以实现!参考“3. rJava实现R调用Java”,只要装好JAVA,配好环境变量就行了。不过这种语法,并不是标准的JAVA语法。写JAVA的人,会很不习惯。
我在开发过程中,一般习惯使用JAVA调用R。JVM会加载RVM的虚拟机,在一个进程中完成。
你的Language engines的想法非常好!如果不用R做中间转换层,而是用JAVA或者C在中间转换,前景应该会更大。
我不熟悉Java,所以也许问不好问题:我的猜想是Java里面应该也有eval()之类的函数可以运行一段代码,然后我在R里面创建一个Java运行器,然后不断j$eval(‘code code code’)。这个具体怎么弄我不清楚,不知是否能给个例子?谢谢。
1. JAVA里没有eval()函数。你希望eval()执行的代码,是Linux命令?还是其他语言的代码?
如果是linux命令,可以用下面的代码
Runtime.getRuntime().exec(“dir”)
如果是其他语言的代码,会比较麻烦,需要安装对应语言的环境。
2. R里面创建一个Java运行器,rJava就是做的这件事。通过JNI来完成,R对Java的调用。依赖于rJava的函数可以实现,你要的j$eval(‘code code code’)功能。
3. JAVA是编译运行的语言,与R,Python, Ruby是完全不一样的语言结构。所有都是JAVA代码,都编译后才能运行,我不知道是不是这个原因,所以咱们对问题的理解是不一样的?!
我希望eval()执行的就是Java代码,因为Java是编译型语言,所以eval()可以先编译它再运行。我之前做的大多都是解释型语言(除了C和C++之外),所以简单一些,我现在又想了想,可能没太大必要做Java,等用户真有需求了再说吧。
要用eval()执行Java代码,虽然有解决方案,但是复杂度是很高的。如果没有一个很懂JAVA的帮你,这个事难啊。还是先往后放放吧,等有需求再做吧。
最近发现有一个叫jvmr的包,可以有类似的功能。在我的电脑上,示例代码里scala比java的代码快一些,http://t.cn/RhukXtW。
谢谢,这个看起来不错,我有空仔细研究一下。
jvmr似乎还是依赖于rJava的,这样其实并不能解决R本身的瓶境。
丹,如果用java写好了算法, 然后用rJava来调用就可以了咯?那么说r与mahaout的链接可以通过rJava来实现,再加上rhadoop的转化?
1. Java写算法,R调用Java,这是一种标准的用法。像RJDBC这样的包,都是通过这种方案实现的。
2. r与mahout,确实可以通过rjava来实现,但这样做的意义不是太大,除非你准备开发一个Rmahout的包。
Mahout是一套完整的机器学习算法框架,天生已接入hadoop,能够把Mahout使用好的人,在算法上面不用依赖R,完全有能力JAVA实现。
3. rhadoop,是一条打能R与Hadoop的通道,让R语言处理大数据成为可能。不过,rmr2的开发,依然是一件很难的事情。
[…] 参考文章: Rserve与Java的跨平台通信 解惑rJava R与Java的高速通道 […]
[…] 另一个R和Java通信的库JRI,并不支持多会话机制。关于R和Java通信的其他文章,请参考:解惑rJava R与Java的高速通道, Rserve与Java的跨平台通信 […]
刚接触rjava,配置很长时间没成功。返回这个错误:Warning in install.packages :
installation of package ‘rJava’ had non-zero exit status
进行sudo R CMD javareconf这步时,
conftest.c:1:17: 致命错误: jni.h:没有那个文件或目录
编译中断。
make: *** [conftest.o] 错误 1
Unable to compile a JNI program
网上搜了很长时间,没配置成功,请问该怎么解决?
似乎没装JDK吧?
ubuntu下装eclipse着,可以使用,查询有下面结果:
:~$ echo $JAVA_HOME
/usr/lib/jvm/java-7-sun
:~$ java -version
java version “1.6.0_27”
OpenJDK Runtime Environment (IcedTea6 1.12.6) (6b27-1.12.6-1ubuntu0.12.04.4)
OpenJDK 64-Bit Server VM (build 20.0-b12, mixed mode)
改成:SUN JDK
错误于.jcall(“RJavaTools”, “Ljava/lang/Object;”, “invokeMethod”, cl, :
java.lang.NoClassDefFoundError: Could not initialize class org.apache.log4j.LogManager
这是怎么回事呢?找不到类吗?
我不知道你的程序是什么样子的,从错误来看,是没有找到这个类。org.apache.log4j.LogManager
我用的是R3.0.3版本,hadoop是2.2版本,安装完成后,进入R命令行,library(rhdfs),然后hdfs.init(),就出现了以上错误。如果没有找到这个类,我怎么加载上呢?
R2.15.3 + Hadoop 1.0.x
linux下运行Java时,会报这个错误
Cannot find JRI native library!
Please make sure that the JRI native library is in a directory listed in java.library.path.
java.lang.UnsatisfiedLinkError: no jri in java.library.path
这个包也可以单独下载,然后加载到运行时环境。
linux安装完rJava后,有jri.so吗? LD_LIBRARY_PATH应该配置到哪个目录?jri的几个jar包都有了,但是报这个错误,是不是环境变量配置不对?能把你配置的环境变量给我看一下吗,尤其是 java.library.path,谢谢了
文章里不是有java.library.path和运行环境。
~ java -Djava.library.path=/usr/local/lib/R/site-library/rJava/jri -cp /usr/local/lib/R/site-library/rJava/jri/JRI.jar:/home/conan/R/DemoRJava/DemoRJava.jar org.conan.r.rjava.DemoRJava
您好,我和你遇到了同样的问题,请问下你是怎么解决的。linux下运行Java时,会报这个错误
Cannot find JRI native library!
Please make sure that the JRI native library is in a directory listed in java.library.path.
java.lang.UnsatisfiedLinkError: no jri in java.library.path
我64位的R,64位的eclipse,64位的JDK 不行啊,R里面报错说LoadLibrary failure: %1 不是有效的 Win32 应用程序。 全部换成32位的没有问题,但是那样做的别的工作都要换,很麻烦,楼主有办法解决在64位上面按rjava吗
在Linux环境中,一般不会出现这个问题。如果必须用Window,那只能在麻烦中操作了。
樓主你好,
請問R語言的底層運作架構是RVM嘛?
RVM是如何運作的?
RVM,R Virtual Machine运行时环境,如何动作要查官方文档了。
/usr/R-3.1.2/lib64/R/library/rJava/jri/libjri.so: libR.so: 无法打开共享对象文件,没有那个文件或目录
/usr/R-3.1.2/lib64/R/library/rJava/jri/libjri.so: libR.so: 无法打开共享对象文件,没有那个文件或目录 我也遇到了同样的问题,请问您是怎么解决的
在eclipse中设置了: -Djava.library.path=:/usr/R-3.1.2/lib64/R/library/rJava/jri
运行DemoRJava, 显示/usr/R-3.1.2/lib64/R/library/rJava/jri/libjri.so: libR.so: 无法打开共享对象文件,没有那个文件或目录
不知道该如何处理
版本不同,可能R的安装目录是不一样的。用linux find函数找一下。
遇到同样的问题,请问你是怎么解决的呢?
win系统的目录下面
D:toolR-3.2.3libraryrJavajrix64jri.dll
linux是 .so的
我在Linux系统的Eclipse中,VM配置为:-Djava.library.path=”/opt/R-3.2.3/library/rJava/jri/libjri.so” ,然后出现报错:Cannot find JRI native library!
Please make sure that the JRI native library is in a directory listed in java.library.path.
java.lang.UnsatisfiedLinkError: no jri in java.library.path
-Djava.library.path=”/opt/R-3.2.3/library/rJava/jri/
指定目录而不是文件,是不是这个问题?
-Djava.library.path=”/opt/R-3.2.3/library/rJava/jri/ 或者 -Djava.library.path=”/opt/R-3.2.3/library/rJava/jri 都会报以下的错误:
Cannot find JRI native library!
Please make sure that the JRI native library is in a directory listed in java.library.path.
java.lang.UnsatisfiedLinkError: /opt/R-3.2.3/library/rJava/jri/libjri.so: libR.so: 无法打开共享对象文件: 没有那个文件或目录
确定一下,你的目录里有这个文件吗?
目录里有这个文件,jdk装的事sun的,不是openjdk。
把编译后的类文件拷出来放到/opt/R-3.2.3/library/rJava/jri/examples目录下,然后通过运行/opt/R-3.2.3/library/rJava/jri/run 执行文件可以正常运行
这样吧,你直接把rJava下面的*.jar都复制你的项目类库里面吧,不要用这种-D的方式加载了。应该就行了。
/usr/R-3.1.2/lib64/R/library/rJava/jri/ 下面存在JRI.jar, JRIEngine.jar及REngine.jar,以及libjri.so等文件
我的rJava没有libjri.so文件,你的rJava是如何安装的?能不能告诉我下你是使用install.packages还是自己下载的,如果是install.packages,你选的那个源,如果是自己下载是在哪下载的?谢谢
楼主,我的错误是这样的,麻烦问一下应该如何解决呀
Cannot find JRI native library!
Please make sure that the JRI native library is in a directory listed in java.library.path.
java.lang.UnsatisfiedLinkError: D:TDDownloadR_softwareinstallR-3.2.2libraryrJavajrix64jri.dll: %1 不是有效的 Win32 应用程序。
不好意思,回复晚了。
UnsatisfiedLinkError这个错误,应该是版本的问题。你的JAVA和jri.dll不兼容。
rJava在tomcat里运行,new REngine()第二次会导致tomcat崩溃。
要看你是怎么加载的。 一个DDL,只能被JVM加载一次。
rJava下的3个jar包:JRI.jar JRIEngine.jar REngine.jar 本就在项目底下,还是照样问题
我也不知道,你哪里出了问题,环境要调啊。
版主你好,我想问下安装rjava时报如下错,怎么解决,系统为centos6.2,jdk版本1.7
rjava.c:52: warning: ignoring return value of ‘read’, declared with attribute warn_unused_result
gcc -m64 -std=gnu99 -o libjri.so Rengine.o jri.o Rcallbacks.o Rinit.o globals.o rjava.o -shared -L/usr/java/jdk1.7.0_79/jre/lib/amd64/server -ljvm -Wl,–export-dynamic -fopenmp -L/usr/lib64/R/lib -lR -lrt -ldl -lm -licuuc -licui18n
/usr/bin/ld: cannot find -licuuc
collect2: ld returned 1 exit status
make[2]: *** [libjri.so] Error 1
make[2]: Leaving directory `/tmp/RtmpTiqE2j/R.INSTALL36592d83da75/rJava/jri/src’
make[1]: *** [src/JRI.jar] Error 2
make[1]: Leaving directory `/tmp/RtmpTiqE2j/R.INSTALL36592d83da75/rJava/jri’
make: *** [jri] Error 2
ERROR: compilation failed for package ‘rJava’
* removing ‘/usr/lib64/R/library/rJava’
看起来是环境的问题,换个Java或换个R再试试。
是的,我换了java版本就OK了,谢谢
编译错误,看上去是JAVA和R的版本不匹配。
楼主,我的错误是这样的,麻烦请教一下应该如何解决呀
Cannot find JRI native library!
Please make sure that the JRI native library is in a directory listed in java.library.path.
java.lang.UnsatisfiedLinkError: D:TDDownloadR_softwareinstallR-3.2.2libraryrJavajrix64jri.dll: %1 不是有效的 Win32 应用程序。
请问,我如果用java语言调用R语言卡方分析,怎么在java中输出多个分析结果
用eval()执行完,卡方分析的结果在java里面怎么显示
你可以查看一下R语言代码里怎么实现的,如果是用cat, print输出的,就不能返回到java里;如果是return的,就可以返回来。
> chisq.test,
structure(list(statistic = STATISTIC, parameter = PARAMETER,
p.value = PVAL, method = METHOD, data.name = DNAME, observed = x,
expected = E, residuals = (x – E)/sqrt(E), stdres = (x –
E)/sqrt(V)), class = “htest”)
返回的是对象,这个会对应java的数据结构。
返回的structure是这个数据结构吗
是的,会映射成JAVA的一个结构。
谢谢