在java代码中执行R代码或函数(一)

以下代码在win7,jdk 1.7,eclipse 4.4.2,R 3.1.2下运行通过。

1 搭建R环境

在使用java代码调用R代码之前,需要先保证本机环境已搭建R环境,可以正常执行R代码。否则,在R开发工具中尚不能执行R代码,在java中调用R很有可能会失败。
下载R windows安装包,https://cran.r-project.org/bin/windows/base/
选择一个版本,解压,执行\R-3.1.2\bin\x64\Rgui.exe,打开R界面窗口,会显示命令行。执行以下命令,验证R已正确安装;

sessionInfo()
会显示R版本、本机操作系统等信息
x <- c(1,2,3)
x * 10
会显示[1] 10 20 30

2 编写R测试代码

点击左上角菜单,新建R文件,保存到某一个目录下,路径中最好没有空格和括号等特殊字符,命名为1.R
将下面内容复制到里面保存。

test_no_param <- function (){
  return(100)
}

# 入参为一个list和一个整数,出参为一个list
test_param_list <- function (x, y) {
  x[,2] <- x[,2] * y

  return(x)
}

3 执行R代码

全选代码,点击工具栏运行代码图标,加载两个函数,R Console窗口命令行会输出相关信息。在命令行输入下面代码,结果如下:

test_no_param()
[1] 100
在命令行输入下面代码,结果如下:
c1 <- c(“a”,”b”,”c”)
c2 <- c(1, 2, 3)
x <- data.frame(c1,c2)
x
c1 c2
1 a 1
2 b 2
3 c 3
y <- test_param_list(x, 10)
y
c1 c2
1 a 10
2 b 20
3 c 30

4 安装rJava包

如果上面两个函数执行无问题,表示本地已搭建好R环境。在命令行执行:
install.packages(“rJava”)
选择国内的一个源,R会安装一个包,rJava。接下来通过这个包,实现在java代码中调用上面的函数。

5 在系统环境变量中添加R路径

新建R_HOME的变量,值为R的根路径,如E:\R\R-3.1.2;
在PATH中添加 %R_HOME%;%R_HOME%/bin/x64;%R_HOME%/library/rJava/jri/x64; 保存;
打开cmd窗口,输入R,正常会显示R版本信息,并进入R代码执行模式,输入quit()退出。表示R已配置到系统环境变量中。

6 编译路径添加相关jar

在R的安装目录(\R-3.1.2\library\rJava\jri)下,找到三个jar包:JRI.jar,JRIEngine.jar,REngine.jar。在eclipse中新建一个java工程,将三个jar包添加到工程编译路径下。
新建Test2.java,代码如下:

package com;

import java.util.Arrays;

import org.rosuda.JRI.REXP;
import org.rosuda.JRI.RList;
import org.rosuda.JRI.RVector;
import org.rosuda.JRI.Rengine;

/**
 * 使用rJava包,调用R代码中的函数
 * 
 * @author frank
 * @since 2016-11-14
 *
 */
public class Test2 {

    public static void main(String[] args) {
        Test2 test2 = new Test2();
        test2.method2();
    }

    /**
     * 加载R文件,调用函数
     */
    @SuppressWarnings("deprecation")
    public void method2(){
        // R文件全路径
        String filePath = "D:\\1.R";

        // 初始化R解析类
        Rengine engine = new Rengine(null, false, null);
        System.out.println("Rengine created, waiting for R");

        // 等待解析类初始化完毕
        if (!engine.waitForR()) {
            System.out.println("Cannot load R");
            return;
        }
        // 将文件全路径复制给R中的一个变量
        engine.assign("fileName", filePath);
        // 在R中执行文件。执行后,文件中的两个函数加载到R环境中,后续可以直接调用
        engine.eval("source(fileName)");
        System.err.println("R文件执行完毕");

        {
            // 直接调用无参的函数,将结果保存到一个对象中
            REXP rexp = engine.eval("test_no_param()");
            System.err.println(rexp);
            // 已知返回值的类型,故将其转换为double,供其他代码使用
            double d = rexp.asDouble();
            System.err.println(d);
            System.err.println("---------------1");
        }

        {
            // 定义一个数组,与R中c1集合对应
            String[] arr1 = new String[]{"a", "b", "c"};
            // 将数组复制给R中的变量c1。R中变量无需预先定义
            engine.assign("c1", arr1);

            // 定义一个数组,与R中c2集合对应
            double[] arr2 = new double[]{1, 2, 3};
            // 将数组复制给R中的变量c2
            engine.assign("c2", arr2);
            // 将c1 c2连接为一个集合(R中的数据集,类似java的list),赋值给一个变量
            engine.eval("x <- data.frame(c1, c2)");
            // 将一个数值保存到一个变量中
            engine.eval("y <- 10");

            // 入参为list,出参为list。调用R中函数,将结果保存到一个对象中。
            REXP rexp = engine.eval("test_param_list(x, y)");
            System.err.println(rexp);

            // 解析rexp对象,转换数据格式

            // list的标题
            RList list = rexp.asList();
            String[] key = list.keys();
            System.err.println(Arrays.toString(key));
            if(key != null){
                int i = 0;
                while (i < key.length){
                    i++;
                }
            }
            // list的数据
            RVector v =  rexp.asVector();
            for(int i=0; i<v.size(); i++){
                REXP rexpTemp = (REXP) v.get(i);
                if(REXP.INTSXP == rexpTemp.rtype){
                    int[] arr = rexpTemp.asIntArray();
                    System.err.println(Arrays.toString(arr));
                } else if(REXP.STRSXP == rexpTemp.rtype){
                    String[] arr = rexpTemp.asStringArray();
                    System.err.println(Arrays.toString(arr));
                } else if(REXP.REALSXP == rexpTemp.rtype){
                    double[] arr = rexpTemp.asDoubleArray();
                    System.err.println(Arrays.toString(arr));
                }
            }
            System.err.println("---------------2");
        }

        engine.stop();
    }



}

jar包maven配置:

<properties>
    <rjava.version>0.9-7</rjava.version>
</properties>


<!-- rjava -->
<!-- https://mvnrepository.com/artifact/com.github.lucarosellini.rJava/JRIEngine -->
<dependency>
    <groupId>com.github.lucarosellini.rJava</groupId>
    <artifactId>JRIEngine</artifactId>
    <version>${rjava.version}</version>
</dependency>
<dependency>
    <groupId>com.github.lucarosellini.rJava</groupId>
    <artifactId>REngine</artifactId>
    <version>${rjava.version}</version>
</dependency>
<dependency>
    <groupId>com.github.lucarosellini.rJava</groupId>
    <artifactId>JRI</artifactId>
    <version>${rjava.version}</version>
</dependency>

7 运行java代码

正常输出如下结果:

Rengine created, waiting for R
R文件执行完毕
[REAL* (100.0)]
100.0
---------------1
[VECTOR ([FACTOR {levels=("a","b","c"),ids=(0,1,2)}], [REAL* (10.0, 20.0, 30.0)])]
[c1, c2]
null
[10.0, 20.0, 30.0]
---------------2

8 备注1

至此,已实现在java中调用R函数、执行R代码。test_param_list入参、出参均为list,复杂的参数都可以使用list进行传输,基本能满足常见的java调用R函数的业务场景。执行过程中,若报错,可google上搜索结果。

9 备注2

R安装目录\R\R-3.1.2\library\rJava\jri\examples下有官方示例代码,可参考。需要注意的是:编写业务代码时不要调用rni开头的函数,此类函数为低级别api。示例代码有相关提示。

这里写图片描述

  • 1
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 5
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值