R是统计计算的强大工具,而JAVA是做应用系统的主流语言,两者天然具有整合的需要。关于整合,一方面,R中可以创建JAVA对象调用JAVA方法,另一方面,JAVA中可以转换R的数据类型调用R的函数,互相取长补短。现在也有一个项目JGR,用JAVA做R的图形界面,可以实现高亮显示自动补全等,还能让JAVA和R互相调用。
关于R中调用JAVA,我想主要是为了利用其面向对象的特性,毕竟R语言近来很致力于向面向对象发展,有个很好的项目rJava可以实现,在www.rforge.net/rJava上。R中调JAVA对我似乎意义不大,本文主要介绍JAVA中调用R。
JAVA很适合开发应用系统,但是数学建模和计算能力非其所长,如果该系统需要进行大量的统计或者优化的计算,调用R是一种很好的方式。JAVA负责系统的构建,R用来做运算引擎,从而实现应用型和分析性相结合的系统。
目前网上有两种方式使用java调用R。
首先要介绍的是Rserve的方式,这是一个基于TCP/IP的服务器,通过二进制协议传输数据,可以提供远程连接,使得客户端语言能够调用R。目前Rserve作为一个package发布在CRAN上,可以直接使用install.packages("Rserve")进行安装。需要使用时在R控制台下加载该包,然后输入命令Rserve(),开启服务器,就可以供客户端调用。
其客户端可以有多种,这里只介绍JAVA客户端。最早的客户端包是JRclient,在www.rosuda.org/Rserve上还可以下载到,但是现在该项目全部移到了www.rforge.net/Rserve,使用REngine作客户端(和JRI一致),在该网站下可以下载到REngine.jar和RserveEngine.jar两个文件。如果用eclipse开发的话,在工程属性中导入这两个外部的jar包,就可以正常使用了。
首先建立一个新的连接,然后就可以使用eval之类的方法将R中的表达式传到服务器端,通过R求值后传回JAVA中REXP类型的变量,然后打印出来,整个过程非常简单。由于不需要对R进行初始化,因此速度会比较快。在其他系统下可以同时建立多个连接,但是在Windows下只允许同时打开一个连接,后续的连接都会共有相同的命名空间。官网上不建议在Windows下使用Rserve,因为会丧失很多性能,他们推荐可以考虑DCOM的方式。不过DCOM那个工程没有现成的jar包可用,其实如果是拿R做分析系统中的运算引擎,单连接够用了。
(一) 在R里下载“Rserve”包,并安装
安装好后,
运行如下命令启动“Rserver”
> library(Rserve) > Rserve()
Starting Rserve... "D:\PROGRA~1\R\R-30~1.1\library\Rserve\libs\i386\Rserve.exe" > |
(二) 建立java工程,导入必要的包,写出测试用例
目录结构如下(标红色的是需要的):
Test.java 内容
package com.rTest;
import org.rosuda.REngine.REXP; import org.rosuda.REngine.Rserve.RConnection;
public class Test { public static void main(String[] args) { try { RConnection c = new RConnection(); REXP x = c.eval("R.version.string"); System.out.println(x.asString()); } catch (Exception e) { e.printStackTrace(); } } } |
运行即可
org.rosuda.REngine.Rserve.RserveException: Cannot connect: Connection refused: connect at org.rosuda.REngine.Rserve.RConnection. at org.rosuda.REngine.Rserve.RConnection. at org.rosuda.REngine.Rserve.RConnection. at com.rTest.Test.main(Test.java:9)
|
这是由于“Rserve” 服务器没有启动起来的原因,试试在R内运行如下语句
> library(Rserve) > Rserve()
|
另一种方式是JRI,全名是Java/R Interface,这是一种完全不同的方式,通过调用R的动态链接库从而利用R中的函数等。目前该项目已经成了rJava的子项目,不再提供单独的JRI的版本。因此使用时简单地通过install.packages("rJava")安装rJava就行,在安装文件夹中,可以看到一个jri的子文件夹,里面有自带的例子可以用来测试。
装好后要修改系统的环境变量,在PATH中添加%R_HOME%/bin和%R_HOME%/library/rJava/jri,注意R_HOME的路径要正确,重启系统使之生效。使用时同样在eclipse里导入外部的jar包(在www.rforge.net/rJava下载JRI.jar、REngine.jar和JRIEngine.jar这三个文件),在rJava包安装目录下的jri/examples里有现成的例子(rtest.java和rtest2.java),可以测试是否成功。
(一) 在R中下载安装“Rjava”包
(二) 配置环境变量
我自己的path如下:
D:\Program Files\Java\jdk1.7.0_09\bin;D:\Program Files\R\R-3.0.1\bin\i386;D:\Program Files\R\R-3.0.1\library\rJava\jri;D:\Program Files\R\R-3.0.1\library\rJava\jri\i386
(三) 建立java工程
标红线的是必须的
Rtest 和Rest2 都是Rjava例子里的
package com.rTest; import java.io.*; import java.awt.Frame; import java.awt.FileDialog;
import java.util.Enumeration;
import org.rosuda.JRI.Rengine; import org.rosuda.JRI.REXP; import org.rosuda.JRI.RList; import org.rosuda.JRI.RVector; import org.rosuda.JRI.RMainLoopCallbacks;
class TextConsole implements RMainLoopCallbacks { public void rWriteConsole(Rengine re, String text, int oType) { System.out.print(text); }
public void rBusy(Rengine re, int which) { System.out.println("rBusy("+which+")"); }
public String rReadConsole(Rengine re, String prompt, int addToHistory) { System.out.print(prompt); try { BufferedReader br=new BufferedReader(new InputStreamReader(System.in)); String s=br.readLine(); return (s==null||s.length()==0)?s:s+"\n"; } catch (Exception e) { System.out.println("jriReadConsole exception: "+e.getMessage()); } return null; }
public void rShowMessage(Rengine re, String message) { System.out.println("rShowMessage \""+message+"\""); }
public String rChooseFile(Rengine re, int newFile) { FileDialog fd = new FileDialog(new Frame(), (newFile==0)?"Select a file":"Select a new file", (newFile==0)?FileDialog.LOAD:FileDialog.SAVE); fd.show(); String res=null; if (fd.getDirectory()!=null) res=fd.getDirectory(); if (fd.getFile()!=null) res=(res==null)?fd.getFile():(res+fd.getFile()); return res; }
public void rFlushConsole (Rengine re) { }
public void rLoadHistory (Rengine re, String filename) { }
public void rSaveHistory (Rengine re, String filename) { } }
public class rtest { public static void main(String[] args) { // just making sure we have the right version of everything if (!Rengine.versionCheck()) { System.err.println("** Version mismatch - Java files don't match library version."); System.exit(1); } System.out.println("Creating Rengine (with arguments)"); // 1) we pass the arguments from the command line // 2) we won't use the main loop at first, we'll start it later // (that's the "false" as second argument) // 3) the callbacks are implemented by the TextConsole class above Rengine re=new Rengine(args, false, new TextConsole()); System.out.println("Rengine created, waiting for R"); // the engine creates R is a new thread, so we should wait until it's ready if (!re.waitForR()) { System.out.println("Cannot load R"); return; }
/* High-level API - do not use RNI methods unless there is no other way to accomplish what you want */ try { REXP x; re.eval("data(iris)",false); System.out.println(x=re.eval("iris")); // generic vectors are RVector to accomodate names RVector v = x.asVector(); if (v.getNames()!=null) { System.out.println("has names:"); for (Enumeration e = v.getNames().elements() ; e.hasMoreElements() ;) { System.out.println(e.nextElement()); } } // for compatibility with Rserve we allow casting of vectors to lists RList vl = x.asList(); String[] k = vl.keys(); if (k!=null) { System.out.println("and once again from the list:"); int i=0; while (i } // get boolean array System.out.println(x=re.eval("iris[[1]]>mean(iris[[1]])")); // R knows about TRUE/FALSE/NA, so we cannot use boolean[] this way // instead, we use int[] which is more convenient (and what R uses internally anyway) int[] bi = x.asIntArray(); { int i = 0; while (i System.out.println(""); } // push a boolean array boolean by[] = { true, false, false }; re.assign("bool", by); System.out.println(x=re.eval("bool")); // asBool returns the first element of the array as RBool // (mostly useful for boolean arrays of the length 1). is should return true System.out.println("isTRUE? "+x.asBool().isTRUE()); // now for a real dotted-pair list: System.out.println(x=re.eval("pairlist(a=1,b='foo',c=1:5)")); RList l = x.asList(); if (l!=null) { int i=0; String [] a = l.keys(); System.out.println("Keys:"); while (i System.out.println("Contents:"); i=0; while (i } System.out.println(re.eval("sqrt(36)")); } catch (Exception e) { System.out.println("EX:"+e); e.printStackTrace(); } // Part 2 - low-level API - for illustration purposes only! //System.exit(0); // simple assignment like a<-"hello" (env=0 means use R_GlobalEnv) long xp1 = re.rniPutString("hello"); re.rniAssign("a", xp1, 0); // Example: how to create a named list or data.frame double da[] = {1.2, 2.3, 4.5}; double db[] = {1.4, 2.6, 4.2}; long xp3 = re.rniPutDoubleArray(da); long xp4 = re.rniPutDoubleArray(db); // now build a list (generic vector is how that's called in R) long la[] = {xp3, xp4}; long xp5 = re.rniPutVector(la); // now let's add names String sa[] = {"a","b"}; long xp2 = re.rniPutStringArray(sa); re.rniSetAttr(xp5, "names", xp2); // ok, we have a proper list now // we could use assign and then eval "b<-data.frame(b)", but for now let's build it by hand: String rn[] = {"1", "2", "3"}; long xp7 = re.rniPutStringArray(rn); re.rniSetAttr(xp5, "row.names", xp7); long xp6 = re.rniPutString("data.frame"); re.rniSetAttr(xp5, "class", xp6); // assign the whole thing to the "b" variable re.rniAssign("b", xp5, 0); { System.out.println("Parsing"); long e=re.rniParse("data(iris)", 1); System.out.println("Result = "+e+", running eval"); long r=re.rniEval(e, 0); System.out.println("Result = "+r+", building REXP"); REXP x=new REXP(re, r); System.out.println("REXP result = "+x); } { System.out.println("Parsing"); long e=re.rniParse("iris", 1); System.out.println("Result = "+e+", running eval"); long r=re.rniEval(e, 0); System.out.println("Result = "+r+", building REXP"); REXP x=new REXP(re, r); System.out.println("REXP result = "+x); } { System.out.println("Parsing"); long e=re.rniParse("names(iris)", 1); System.out.println("Result = "+e+", running eval"); long r=re.rniEval(e, 0); System.out.println("Result = "+r+", building REXP"); REXP x=new REXP(re, r); System.out.println("REXP result = "+x); String s[]=x.asStringArray(); if (s!=null) { int i=0; while (i } } { System.out.println("Parsing"); long e=re.rniParse("rnorm(10)", 1); System.out.println("Result = "+e+", running eval"); long r=re.rniEval(e, 0); System.out.println("Result = "+r+", building REXP"); REXP x=new REXP(re, r); System.out.println("REXP result = "+x); double d[]=x.asDoubleArray(); if (d!=null) { int i=0; while (i System.out.println(""); } System.out.println(""); } { REXP x=re.eval("1:10"); System.out.println("REXP result = "+x); int d[]=x.asIntArray(); if (d!=null) { int i=0; while (i System.out.println(""); } } re.eval("print(1:10/3)"); if (true) { // so far we used R as a computational slave without REPL // now we start the loop, so the user can use the console System.out.println("Now the console is yours ... have fun"); re.startMainLoop(); } else { re.end(); System.out.println("end"); } } } |
package com.rTest; import java.io.*;
import java.awt.*; import javax.swing.*;
import org.rosuda.JRI.Rengine; import org.rosuda.JRI.REXP; import org.rosuda.JRI.RMainLoopCallbacks; import org.rosuda.JRI.RConsoleOutputStream;
class TextConsole2 implements RMainLoopCallbacks { JFrame f;
public JTextArea textarea = new JTextArea();
public TextConsole2() { f = new JFrame(); f.getContentPane().add(new JScrollPane(textarea)); f.setSize(new Dimension(800,600)); f.show(); }
public void rWriteConsole(Rengine re, String text, int oType) { textarea.append(text); }
public void rBusy(Rengine re, int which) { System.out.println("rBusy("+which+")"); }
public String rReadConsole(Rengine re, String prompt, int addToHistory) { System.out.print(prompt); try { BufferedReader br=new BufferedReader(new InputStreamReader(System.in)); String s=br.readLine(); return (s==null||s.length()==0)?s:s+"\n"; } catch (Exception e) { System.out.println("jriReadConsole exception: "+e.getMessage()); } return null; }
public void rShowMessage(Rengine re, String message) { System.out.println("rShowMessage \""+message+"\""); }
public String rChooseFile(Rengine re, int newFile) { FileDialog fd = new FileDialog(f, (newFile==0)?"Select a file":"Select a new file", (newFile==0)?FileDialog.LOAD:FileDialog.SAVE); fd.show(); String res=null; if (fd.getDirectory()!=null) res=fd.getDirectory(); if (fd.getFile()!=null) res=(res==null)?fd.getFile():(res+fd.getFile()); return res; }
public void rFlushConsole (Rengine re) { }
public void rLoadHistory (Rengine re, String filename) { }
public void rSaveHistory (Rengine re, String filename) { } }
public class rtest2 { public static void main(String[] args) { System.out.println("Press try { System.in.read(); } catch(Exception e) {}; System.out.println("Creating Rengine (with arguments)"); Rengine re=new Rengine(args, true, new TextConsole2()); System.out.println("Rengine created, waiting for R"); if (!re.waitForR()) { System.out.println("Cannot load R"); return; } System.out.println("re-routing stdout/err into R console"); System.setOut(new PrintStream(new RConsoleOutputStream(re, 0))); System.setErr(new PrintStream(new RConsoleOutputStream(re, 1)));
System.out.println("Letting go; use main loop from now on"); } } |
运行即可 Rtest 运行结果如下:
Creating Rengine (with arguments)
R version 3.0.1 (2013-05-16) -- "Good Sport" Copyright (C) 2013 The R Foundation for Statistical Computing Platform: i386-w64-mingw32/i386 (32-bit)
R is free software and comes with ABSOLUTELY NO WARRANTY. You are welcome to redistribute it under certain conditions. Type 'license()' or 'licence()' for distribution details.
R is a collaborative project with many contributors. Type 'contributors()' for more information and 'citation()' on how to cite R or R packages in publications.
Type 'demo()' for some demos, 'help()' for on-line help, or 'help.start()' for an HTML browser interface to help. Type 'q()' to quit R.
[1] "LC_COLLATE=Chinese_People's Republic of China.936;LC_CTYPE=Chinese_People's Republic of China.936;LC_MONETARY=Chinese_People's Republic of China.936;LC_NUMERIC=C;LC_TIME=Chinese_People's Republic of China.936" Rengine created, waiting for R [VECTOR ([REAL* (5.1, 4.9, 4.7, 4.6, 5.0, 5.4, 4.6, 5.0, 4.4, 4.9, 5.4, 4.8, 4.8, 4.3, 5.8, 5.7, 5.4, 5.1, 5.7, 5.1, 5.4, 5.1, 4.6, 5.1, 4.8, 5.0, 5.0, 5.2, 5.2, 4.7, 4.8, 5.4, 5.2, 5.5, 4.9, 5.0, 5.5, 4.9, 4.4, 5.1, 5.0, 4.5, 4.4, 5.0, 5.1, 4.8, 5.1, 4.6, 5.3, 5.0, 7.0, 6.4, 6.9, 5.5, 6.5, 5.7, 6.3, 4.9, 6.6, 5.2, 5.0, 5.9, 6.0, 6.1, 5.6, 6.7, 5.6, 5.8, 6.2, 5.6, 5.9, 6.1, 6.3, 6.1, 6.4, 6.6, 6.8, 6.7, 6.0, 5.7, 5.5, 5.5, 5.8, 6.0, 5.4, 6.0, 6.7, 6.3, 5.6, 5.5, 5.5, 6.1, 5.8, 5.0, 5.6, 5.7, 5.7, 6.2, 5.1, 5.7, ... (50 more values follow))], [REAL* (3.5, 3.0, 3.2, 3.1, 3.6, 3.9, 3.4, 3.4, 2.9, 3.1, 3.7, 3.4, 3.0, 3.0, 4.0, 4.4, 3.9, 3.5, 3.8, 3.8, 3.4, 3.7, 3.6, 3.3, 3.4, 3.0, 3.4, 3.5, 3.4, 3.2, 3.1, 3.4, 4.1, 4.2, 3.1, 3.2, 3.5, 3.6, 3.0, 3.4, 3.5, 2.3, 3.2, 3.5, 3.8, 3.0, 3.8, 3.2, 3.7, 3.3, 3.2, 3.2, 3.1, 2.3, 2.8, 2.8, 3.3, 2.4, 2.9, 2.7, 2.0, 3.0, 2.2, 2.9, 2.9, 3.1, 3.0, 2.7, 2.2, 2.5, 3.2, 2.8, 2.5, 2.8, 2.9, 3.0, 2.8, 3.0, 2.9, 2.6, 2.4, 2.4, 2.7, 2.7, 3.0, 3.4, 3.1, 2.3, 3.0, 2.5, 2.6, 3.0, 2.6, 2.3, 2.7, 3.0, 2.9, 2.9, 2.5, 2.8, ... (50 more values follow))], [REAL* (1.4, 1.4, 1.3, 1.5, 1.4, 1.7, 1.4, 1.5, 1.4, 1.5, 1.5, 1.6, 1.4, 1.1, 1.2, 1.5, 1.3, 1.4, 1.7, 1.5, 1.7, 1.5, 1.0, 1.7, 1.9, 1.6, 1.6, 1.5, 1.4, 1.6, 1.6, 1.5, 1.5, 1.4, 1.5, 1.2, 1.3, 1.4, 1.3, 1.5, 1.3, 1.3, 1.3, 1.6, 1.9, 1.4, 1.6, 1.4, 1.5, 1.4, 4.7, 4.5, 4.9, 4.0, 4.6, 4.5, 4.7, 3.3, 4.6, 3.9, 3.5, 4.2, 4.0, 4.7, 3.6, 4.4, 4.5, 4.1, 4.5, 3.9, 4.8, 4.0, 4.9, 4.7, 4.3, 4.4, 4.8, 5.0, 4.5, 3.5, 3.8, 3.7, 3.9, 5.1, 4.5, 4.5, 4.7, 4.4, 4.1, 4.0, 4.4, 4.6, 4.0, 3.3, 4.2, 4.2, 4.2, 4.3, 3.0, 4.1, ... (50 more values follow))], [REAL* (0.2, 0.2, 0.2, 0.2, 0.2, 0.4, 0.3, 0.2, 0.2, 0.1, 0.2, 0.2, 0.1, 0.1, 0.2, 0.4, 0.4, 0.3, 0.3, 0.3, 0.2, 0.4, 0.2, 0.5, 0.2, 0.2, 0.4, 0.2, 0.2, 0.2, 0.2, 0.4, 0.1, 0.2, 0.2, 0.2, 0.2, 0.1, 0.2, 0.2, 0.3, 0.3, 0.2, 0.6, 0.4, 0.3, 0.2, 0.2, 0.2, 0.2, 1.4, 1.5, 1.5, 1.3, 1.5, 1.3, 1.6, 1.0, 1.3, 1.4, 1.0, 1.5, 1.0, 1.4, 1.3, 1.4, 1.5, 1.0, 1.5, 1.1, 1.8, 1.3, 1.5, 1.2, 1.3, 1.4, 1.4, 1.7, 1.5, 1.0, 1.1, 1.0, 1.2, 1.6, 1.5, 1.6, 1.5, 1.3, 1.3, 1.3, 1.2, 1.4, 1.2, 1.0, 1.3, 1.2, 1.3, 1.3, 1.1, 1.3, ... (50 more values follow))], [FACTOR {levels=("setosa","versicolor","virginica"),ids=(0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2)}])] has names: Sepal.Length Sepal.Width Petal.Length Petal.Width Species and once again from the list: Sepal.Length Sepal.Width Petal.Length Petal.Width Species [BOOLi* ] F F F F F F F F F F F F F F F F F F F F F F F F F F F F F F F F F F F F F F F F F F F F F F F F F F T T T F T F T F T F F T T T F T F F T F T T T T T T T T T F F F F T F T T T F F F T F F F F F T F F T F T T T T F T T T T T T F F T T T T T T F T T T T T T T T T T T T T T T T T T T T F T T T T T T T [BOOLi* ] isTRUE? true [LIST [REAL* (1.0)]:[SYMBOL a],([LIST [STRING "foo"]:[SYMBOL b],([LIST [INT* (1, 2, 3, 4, 5)]:[SYMBOL c],(null)])])] Keys: a b c Contents: [REAL* (1.0)] [STRING "foo"] [INT* (1, 2, 3, 4, 5)] [REAL* (6.0)] Parsing Result = 59278824, running eval Result = 66228464, building REXP REXP result = [STRING "iris"] Parsing Result = 54717432, running eval Result = 59554488, building REXP REXP result = [VECTOR ([REAL* (5.1, 4.9, 4.7, 4.6, 5.0, 5.4, 4.6, 5.0, 4.4, 4.9, 5.4, 4.8, 4.8, 4.3, 5.8, 5.7, 5.4, 5.1, 5.7, 5.1, 5.4, 5.1, 4.6, 5.1, 4.8, 5.0, 5.0, 5.2, 5.2, 4.7, 4.8, 5.4, 5.2, 5.5, 4.9, 5.0, 5.5, 4.9, 4.4, 5.1, 5.0, 4.5, 4.4, 5.0, 5.1, 4.8, 5.1, 4.6, 5.3, 5.0, 7.0, 6.4, 6.9, 5.5, 6.5, 5.7, 6.3, 4.9, 6.6, 5.2, 5.0, 5.9, 6.0, 6.1, 5.6, 6.7, 5.6, 5.8, 6.2, 5.6, 5.9, 6.1, 6.3, 6.1, 6.4, 6.6, 6.8, 6.7, 6.0, 5.7, 5.5, 5.5, 5.8, 6.0, 5.4, 6.0, 6.7, 6.3, 5.6, 5.5, 5.5, 6.1, 5.8, 5.0, 5.6, 5.7, 5.7, 6.2, 5.1, 5.7, ... (50 more values follow))], [REAL* (3.5, 3.0, 3.2, 3.1, 3.6, 3.9, 3.4, 3.4, 2.9, 3.1, 3.7, 3.4, 3.0, 3.0, 4.0, 4.4, 3.9, 3.5, 3.8, 3.8, 3.4, 3.7, 3.6, 3.3, 3.4, 3.0, 3.4, 3.5, 3.4, 3.2, 3.1, 3.4, 4.1, 4.2, 3.1, 3.2, 3.5, 3.6, 3.0, 3.4, 3.5, 2.3, 3.2, 3.5, 3.8, 3.0, 3.8, 3.2, 3.7, 3.3, 3.2, 3.2, 3.1, 2.3, 2.8, 2.8, 3.3, 2.4, 2.9, 2.7, 2.0, 3.0, 2.2, 2.9, 2.9, 3.1, 3.0, 2.7, 2.2, 2.5, 3.2, 2.8, 2.5, 2.8, 2.9, 3.0, 2.8, 3.0, 2.9, 2.6, 2.4, 2.4, 2.7, 2.7, 3.0, 3.4, 3.1, 2.3, 3.0, 2.5, 2.6, 3.0, 2.6, 2.3, 2.7, 3.0, 2.9, 2.9, 2.5, 2.8, ... (50 more values follow))], [REAL* (1.4, 1.4, 1.3, 1.5, 1.4, 1.7, 1.4, 1.5, 1.4, 1.5, 1.5, 1.6, 1.4, 1.1, 1.2, 1.5, 1.3, 1.4, 1.7, 1.5, 1.7, 1.5, 1.0, 1.7, 1.9, 1.6, 1.6, 1.5, 1.4, 1.6, 1.6, 1.5, 1.5, 1.4, 1.5, 1.2, 1.3, 1.4, 1.3, 1.5, 1.3, 1.3, 1.3, 1.6, 1.9, 1.4, 1.6, 1.4, 1.5, 1.4, 4.7, 4.5, 4.9, 4.0, 4.6, 4.5, 4.7, 3.3, 4.6, 3.9, 3.5, 4.2, 4.0, 4.7, 3.6, 4.4, 4.5, 4.1, 4.5, 3.9, 4.8, 4.0, 4.9, 4.7, 4.3, 4.4, 4.8, 5.0, 4.5, 3.5, 3.8, 3.7, 3.9, 5.1, 4.5, 4.5, 4.7, 4.4, 4.1, 4.0, 4.4, 4.6, 4.0, 3.3, 4.2, 4.2, 4.2, 4.3, 3.0, 4.1, ... (50 more values follow))], [REAL* (0.2, 0.2, 0.2, 0.2, 0.2, 0.4, 0.3, 0.2, 0.2, 0.1, 0.2, 0.2, 0.1, 0.1, 0.2, 0.4, 0.4, 0.3, 0.3, 0.3, 0.2, 0.4, 0.2, 0.5, 0.2, 0.2, 0.4, 0.2, 0.2, 0.2, 0.2, 0.4, 0.1, 0.2, 0.2, 0.2, 0.2, 0.1, 0.2, 0.2, 0.3, 0.3, 0.2, 0.6, 0.4, 0.3, 0.2, 0.2, 0.2, 0.2, 1.4, 1.5, 1.5, 1.3, 1.5, 1.3, 1.6, 1.0, 1.3, 1.4, 1.0, 1.5, 1.0, 1.4, 1.3, 1.4, 1.5, 1.0, 1.5, 1.1, 1.8, 1.3, 1.5, 1.2, 1.3, 1.4, 1.4, 1.7, 1.5, 1.0, 1.1, 1.0, 1.2, 1.6, 1.5, 1.6, 1.5, 1.3, 1.3, 1.3, 1.2, 1.4, 1.2, 1.0, 1.3, 1.2, 1.3, 1.3, 1.1, 1.3, ... (50 more values follow))], [FACTOR {levels=("setosa","versicolor","virginica"),ids=(0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2)}])] Parsing Result = 54722488, running eval Result = 59554264, building REXP REXP result = [STRING* ("Sepal.Length", "Sepal.Width", "Petal.Length", "Petal.Width", "Species")] [0] "Sepal.Length" [1] "Sepal.Width" [2] "Petal.Length" [3] "Petal.Width" [4] "Species" Parsing Result = 54722392, running eval Result = 58316336, building REXP REXP result = [REAL* (-0.18945291321042293, -1.849701024870639, -1.5554362607982648, 0.5990838636624077, -0.3034793177677859, -1.7781090129037724, 0.35644623327794134, -0.17655333079642885, -0.4089712138070159, -1.9775440799762682)] -0.18945291321042293, -1.849701024870639, -1.5554362607982648, 0.5990838636624077, -0.3034793177677859, -1.7781090129037724, 0.35644623327794134, -0.17655333079642885, -0.4089712138070159, -1.9775440799762682
REXP result = [INT* (1, 2, 3, 4, 5, 6, 7, 8, 9, 10)] 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 [1] 0.3333333 0.6666667 1.0000000 1.3333333 1.6666667 2.0000000 2.3333333 [8] 2.6666667 3.0000000 3.3333333 Now the console is yours ... have fun rBusy(0) > print("hello") rBusy(1) [1] "hello" rBusy(0) > |
Press
Creating Rengine (with arguments) 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 at java.lang.ClassLoader.loadLibrary(ClassLoader.java:1860) at java.lang.Runtime.loadLibrary0(Runtime.java:845) at java.lang.System.loadLibrary(System.java:1084) at org.rosuda.JRI.Rengine. at com.rTest.rtest2.main(rtest2.java:73) |
检查下path是否正确,如果正确
重启下Eclipse 即可,如果不行,重启电脑。