JAVA 调用 R 语言


1 简介

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。

2       Rserve的方式

2.1     介绍

首先要介绍的是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做分析系统中的运算引擎,单连接够用了。

2.2     操作步骤

(一)   在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();

       }

    }

运行即可

2.3     可能出现的错误

2.3.1  Connection refused: connect

org.rosuda.REngine.Rserve.RserveException: Cannot connect: Connection refused: connect

    at org.rosuda.REngine.Rserve.RConnection.(RConnection.java:88)

    at org.rosuda.REngine.Rserve.RConnection.(RConnection.java:60)

    at org.rosuda.REngine.Rserve.RConnection.(RConnection.java:44)

    at com.rTest.Test.main(Test.java:9)

这是由于“Rserve” 服务器没有启动起来的原因,试试在R内运行如下语句

> library(Rserve)

> Rserve()

3       JRI 的方式

3.1     介绍

另一种方式是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),可以测试是否成功。

3.2     操作步骤

(一)   在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 to continue (time to attach the debugger if necessary)");

        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)

3.3     可能出现的错误

3.3.1  Cannot find JRI native library!

Press to continue (time to attach the debugger if necessary)

 

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.(Rengine.java:19)

    at com.rTest.rtest2.main(rtest2.java:73)

检查下path是否正确,如果正确

重启下Eclipse 即可,如果不行,重启电脑。