Nodejs 调用 R 脚本 / Nodejs Call R Script

提供一个在Nodejs中调用 R script 方法。我用的node框架是 eggjs,示例代码全是在Egg环境下实现的。你将会看到以前几个方面的内容。

  • R 简介与在Node中调用R Script 的原因
  • 相关环境的搭建与关键Node知识点
  • 调用方式与相关代码

一、R 简介与在Node中调用R Script 的原因

R是用于统计分析、绘图的语言和操作环境。R是属于GNU系统的一个自由、免费、源代码开放的软件,它是一个用于统计计算和统计制图的优秀工具。简单一下,应该要坐这样操作的人都知道这种必备的背景知识。

需要在调用 Node 中调用 R Script,是因为应用中需要对比较复杂的计算公式做翻译,其中会涉及到三角函数,开方或者求幂等数学运算。而直接用 Javascript 翻译后,在公式计算过程中会因为精度的问题导致整个计算结果异常。具体表现如,Math.tan 结果为0.000000000000001等此类计算结果。

大家搜索同类问题的时候,肯定看到排名靠前的 r-scriptnode-rscriptjs-cal-rrscript这些packages。他们写的肯定是可以用的。燃鹅,具体实现的时候可能想到复杂,比如你的是一个长度在一万的Json数组,或者你的R Script在R studio中运行一切如常偏偏在node中调用就报错,甚至你用packeage page上的示例代码都报错。总之情况可能非常复杂。

二、相关环境的搭建与关键Node知识点

2.1 相关环境搭建

首先肯定机器上肯定需要搭建 Node 环境 和 R 的环境,node 环境就不给介绍了。如果你恰好也用的是Eggjs请参照官网

R 环境则只需要安装最新的 R 安装包就可以了。目前最新的版本R version 3.5.1。官网 在官网如下位置。

R 官网

安装好了之后需要配置系统环境变量,移动要配置。这一步非常重要。 在系统便利中将bin,include两个路径加入到系统变量 Path 中,根据自己的安装路径,我是安装在C盘所以路径如下

C:\Program Files\R\R-3.5.1\bin
C:\Program Files\R\R-3.5.1\include
复制代码

系统环境便利

2.2 Nodejs 知识点

其实,在 node 中调用 R script 的实现思路其实只有一个那就是 通过命令行来执行 R Script。我很粗略的查看了之前提到的Package 源码。非常不严谨的下结论,他们的实现思路其实是一样的,不一样的是在参数处理,已经返回值的处理。

R Script 命令行执行脚本是这样的

Rscript R_File_Path Parameter

R_File_Path: .R 文件的据对路径
Parameter: 参数 类型为字符串
复制代码

所以关键问题 “Node 调用R Script” 就成了如何在 "Node中运行命令行"。解决这个问题用的方法就是使用调用Node模块中子进程child_process 中的 exec

var child_process = require('child_process');
var exec = child_process.exec;
复制代码

child_process 具体是什么,这里就不展开了,不然就模糊重点了。因为很多时候,我看别人的文章,作者很好心的把相关知识点都列出来了,讲的很细,很用心。但对我这种心急的工具党来,真的太花时间了,反而模糊了焦点。我想立刻解决的我的问题。 给代码作为参考,详细说明请看官网

三、调用方式与相关代码

所以,下面直接提供代码。代码作为示例参考,并不十分规范,比如egg中获取数据的操作最好放在service里面。

'use strict';

const path = require("path")
const child_process = require('child_process');
const exec = child_process.exec;

const Controller = require('egg').Controller;

class TestRController extends Controller {
  async echo() {
    let Parameter = path.join(__dirname, "./../public/assets/csv/tilt.csv");
    let R_File_Path = path.join(__dirname, "./../public/assets/r/tilt.R");
    let cmd = 'Rscript' + ' "' + R_File_Path + '" ' + Parameter;
    
    exec(cmd, (error, stdout, stderr) => {
        if (error) {
            consle.log(stderr);
        } else {
            console.log(stdout);
        }
    });
  }
}
module.exports = TestRController;

复制代码

其中比较重要的exec方法的回调结果,每个参数什么意思,就看上图需要解释一下或者官网。解释下如果执行后的返回结果,参数传递的小技巧。 如果数据量比较小那么,直接放放在参数中

'Rscript R_File_Path "{a:1,b:'p1'}";
复制代码

这样R Script 可以直接接受的参数字符串,并且也能序列化成JSON后完成进一步的处理。

但是当参数太大的时候,直接这样传参是会出问题的。处理大量数据参数的技巧则是将在参数数据存放在.txt, .json, .csv文件中,直接将参数文件的绝对路径传递R Script 来完成处理。 同样的道理,在数据返回时也一样会有数据量的限制,数据量较小时可直接返回为JSON字符串,如果过大,则由R保存成文件并返回起绝对路径。

此外还有两点值得分享的

  1. R Script 中如何获取参数
args <- commandArgs(trailingOnly = TRUE)
复制代码
  1. 在 Nodejs 中 exec 方法参数都对,代码拼好的cmd命令在cmd.exe能正常执行。但在Node中执行时,就是报 R Script 中用到的Pakckage这个没安装那个没安装。并且在R Studio中无论重装多少次都重复报错。解决办法:

检查 library路径,如C:\Program Files\R\R-3.5.1\library里面到底有没有这样Package。没有则,下载到引用的Package,然后后手动拷贝到这个路径下。

以上是我解决在Nodejs 中Nodejs 调用 R 脚本的方法。

————————————————

第一次写技术类文章,如果对你有帮助的话,我会觉得高兴。如果看到有可以改进的地方,请给我一点建议。希望自己能坚持,以后分享更多自己收获的知识。

猜你喜欢

转载自juejin.im/post/5c163df4e51d453657257f2b
今日推荐