记一次.NET 与R语言交互

这是将近二年前,有一个项目使用.NET相关技术,但是项目中要将写好的R语言的代码,直接通过.NET调用,得到计算结果,遇到了这么多的坑,在此记下一些过程,文档太少,英文不好!!!

  • 如下为开发过程中可能出现的问题!

  • 相关博客介绍

使用的类库是  RDotNet   ,开源地址:R.NET他有官网的:对R.NET的一些介绍 ,这个可能需要翻墙。

我找了很多博客,在CSDN上的代码,基本都是重复的,也没有太多的介绍,一般情况都是官网直接翻译下来的,遇到一些问题时,根本查不到是什么原因。那么,遇到问题,怎么办?

1、看官网,里面有一些示例的链接:这个相当于示例代码库

2、看github上,开源地址的Issue,看不懂英语,也要看,有些问题,看完你就会懂了。

R.NET是什么?

我的理解,R语言就像是SQL语言,用于数据计算,数据处理。R.Net这个类库就类似ADO.NET的技术,帮助我们实现.NET程序访问R语言代码,R.NET就相当于一个驱动程序。当然,严格意义上,我也不知道RDotNet是不是这样子,看他介绍,应该是起一R引擎。。。。(不懂.jpg)

使用RDotNet的步骤:

1、首先,你要看懂一些简单的R程序,就像,你不懂sql 语句,你怎么写ADO.NET程序一样 (安装R的环境,不要装最新的3.5版本,因为,R.NET并没有做到最新的版本,看他的github就知道了,我本地装的3.3.3,一点问题都没有。如果你安装3.5版本,会一直报一个空指针异常,反正我被坑了。)

2、将我上面所说的示例代码库下载下来,从最简单的代码开始看起。

如下为开发过程中可能出现的问题!

  • 而我遇到什么样的问题呢?我是如何解决的?

  • 还有哪些问题需要解决?

  • 这个类库还有哪些问题不能解决,他有哪些缺点?

回答上面的问题.

1.我遇到的问题。

1)、安装过新的R环境3.5导致一直报错,一点思路都没有。如何解决:看github的issue,看到有人提的问题,大意是指。R.NET不能支持到最新的R语言版本。

2)、一个简单的程序,在控制台上执行,是OK的。然而在ASP.NET MVC程序上一直不成功。如何解决:第一步:先把R的环境变量配置好,类似JDK的环境变量配置 找到自己的R语言位置,将32位和64位的环境都配置至path中

 ;C:\Program Files\R\R-3.3.3\bin\i386;C:\Program Files\R\R-3.3.3\bin\x64;

第二步,如何还有问题的话:比如一直报StackOverflowException的异常,建议你看他的issue:这个是他们的讨论原本我也遇到这个问题,但R的版本用了3.3,就没这个错了。

3)、当R的引擎正常结束后,调用 dispose后,下次调用 就会报错,那就不调用 dispose方法吧。那个作者说:There can only be one R engine in a process, and R itself is largely not thread-safe.

2.还有哪些问题需要解决?

  1. 管理员权限运行Rgui,并指定包安装的位置,防止安装到其他目录 此命令设置当前包安装的位置,

.libPaths("C:/Program Files/R/R-3.3.3/library")

此命令查看当前包会安装的位置

.libPaths()
  1. 如果有些包无法正常安装,如果能找到那个包,可直接复制其至目录C:/Program Files/R/R-3.3.3/library

  2. 运行和发布后的代码都应运行在64位机子及平台上。

3.这个类库还有哪些问题不能解决,他有哪些缺点?

  1. 不能兼容所有的R版本,目前只兼容到R3.3.3。

  2. 如下代码在本机windows10 专业版 中文版电脑上运行会乱码

 CharacterVector datFname = engine.CreateCharacter("我是中文");

我研究下代码,是这个类中的方法有问题InternalString  下的方法 StringFromNativeUtf8

       /// <summary>/// Convert utf8 to string/// </summary>/// <param name="utf8">utf8 to convert</param>public static string StringFromNativeUtf8(IntPtr utf8){int len = 0;while (Marshal.ReadByte(utf8, len) != 0) ++len;byte[] buffer = new byte[len];Marshal.Copy(utf8, buffer, 0, buffer.Length);return Encoding.UTF8.GetString(buffer);}

我在我本地调试源码时,发现,如果包含中文时,采用Encoding.Default.GetString(buffer);转换,这里就可以正常转换,但这样子,就只支持中文和英文了。而且,好像在测试过程中,改成Default后,如下方法中包含中文,反而乱码了。

       string[] rownames = engine.GetSymbol("rownames").AsCharacter().ToArray();

所以我准备直接用最简单的方式 ,判断buffer的编码,如果不为UTF8,Convert为UTF8,然后返回,否则,这里就需要多此一举,因为,在测试过程发现,判断UTF8,不准确,明明不是UTF8,还是返回了UTF8,所以在这里需要判断,转换后的数据是否包含中文,如果包含,则直接返回,否则要从Default(根据系统的编码决定),转换为UTF8,就能返回中文 。

       /// <summary>/// Convert utf8 to string/// </summary>/// <param name="utf8">utf8 to convert</param>public static string StringFromNativeUtf8(IntPtr utf8){int len = 0;while (Marshal.ReadByte(utf8, len) != 0) ++len;byte[] buffer = new byte[len];Marshal.Copy(utf8, buffer, 0, buffer.Length);Encoding encoding = GetType(buffer);if (encoding.Equals(Encoding.UTF8)){string r = Encoding.UTF8.GetString(buffer);if (System.Text.RegularExpressions.Regex.IsMatch(r, @"[\u4e00-\u9fbb]+$")){return r;}else{byte[] newBuffer = Encoding.Convert(Encoding.Default, Encoding.UTF8, buffer);return Encoding.UTF8.GetString(newBuffer);}}else{byte[] newBuffer = Encoding.Convert(encoding, Encoding.UTF8, buffer);return Encoding.UTF8.GetString(newBuffer);}}

代码已放到github

由于该 R.NET类库 长期未维护,还是有很多BUG,所以我fork了一份,以便解决部分简单BUG问题, github开源地址

相关博客介绍

  • 用C#调用R语言开发.NET MVC Web服务 此文章中介绍了.NET启动控制台调用R代码,这个思路非常好,一开始对R语言了解甚少,所以还是使用R.NET来实现.NET与R语言的交互,反而耗时耗力。

  • 一键运行R脚本 这个文章让我了解到Rscript.exe这个程序的作用,以及执行方式。

  • c#调用R语言(原创翻译)

由于开发过程中,有个R程序运行时间非常长,最长可达2小时,所以只能以后台任务方式执行,但 RDotNET,一次只能运行一个,不执行完,其他的程序在WEB项目下无法正常运行,看了上面的文章,有了思路 :使用.NET的进程Process起一个cmd命令,类似 java配置好环境变量后可使用java,javac命令一样,配置到Path中后,可直接在cmd中使用如下命令

Rscript.exe "某目录下\test.R"  agruments 

其中R程序包要有双引号   多个参数使用空格分隔 ,如下为.NET下使用Process启动cmd命令,并执行Rscript.exe 命令启动R引擎,让其后台运行,运行结束后,才会往后执行。

    public void Execute(){List<string> arguments = new List<string>{参数};Process cmd = new Process{StartInfo ={FileName = @"Rscript.exe",WorkingDirectory = AppFolders.RSourceCodeFolder,//.R代码的位置 "E:\svn\CHNMed\CHNMed.Web\DataUsers\RSourceCode"UseShellExecute = false,RedirectStandardOutput = true,RedirectStandardError = true,Arguments = " Test.r " + string.Join(" ", arguments),CreateNoWindow = true,//不显示程序窗口}};cmd.Start();//启动程序var output = cmd.StandardOutput.ReadToEnd();var error = cmd.StandardError.ReadToEnd();cmd.WaitForExit();//等待控制台程序执行完成cmd.Close();//关闭该进程Logger.InfoFormat($"参数:{output}出错信息:{error}");}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/307339.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

leetcode293周赛6064. 不含特殊楼层的最大连续楼层数

一:题目 二:上码 // class Solution { // public:// bool find(vector<int>& v,int i) { // for (auto nums:v) { // if (nums i) return true;//包含某个数 就返回true // } // return false; // }// int maxCon…

软件如何优雅地向前兼容?

大家好&#xff0c;我是Z哥。应该有不少程序员受过这样的困扰&#xff0c;特别是做后端的。项目一直在持续不断的迭代&#xff0c;但是呢老版本的代码还不能直接删掉&#xff0c;因为不一定所有的调用端都能在同一时间点完成升级。你是怎么处理这种情况的呢&#xff1f;方法上增…

leetcode293周赛5234. 移除字母异位词后的结果数组

一:题目 二:上码 class Solution { public:/**1.所谓字母异位词就是相同的字母组成的字符串&#xff08;这个字符串可以相同&#xff09;2.首先判断两个字符串中的字母是否相同用map进行计数&#xff0c;然后在另一个字符串中查找某个字符进行--;3.如果最终的map中所有的value…

七国要求科技巨头预留后门 应对马甲芯片高度警惕

日前&#xff0c;美国、英国、日本、澳大利亚、加拿大、新西兰、印度呼吁科技公司设计产品时确保政府可以访问经过加密的消息和内容。其实&#xff0c;西方科技公司配合西方政府在产品中预留后门早已不是新鲜事&#xff0c;斯诺登就曾经爆料多个美国科技巨头配合美国情报部门收…

leetcode78. 子集

一:题目 二:上码 class Solution {/**横向递归的是:我们子集的长度纵向递归的是:我们子集的中元素的更改*/List<List<Integer>> ans new ArrayList<>();List<Integer> path new ArrayList<>();public void getAns(int[] nums,int st) {ans.ad…

跟我一起学Redis之看完这篇比常人多会三种类型实战(又搞了几个小时)

前言对于Redis而言&#xff0c;很多小伙伴只关注其关键的五大基础类型&#xff1a;string、hash、list、set、sorted set(有序集合)&#xff0c;其实还有三种特殊类型在很多应用场景也比较适合使用&#xff0c;分别是&#xff1a;bitmap、geospatial、hyperloglog&#xff1b;上…

leetcode90. 子集 II(树层去重)

一:题目 二:上码 class Solution {/**- 先排序- 树层去重:那么直接在从横向循环中去重即可*/List<List<Integer>> ans new ArrayList<>();List<Integer> path new ArrayList<>();public void getAns(int[] nums,int st) {ans.add(new ArrayLi…

Rancher 2.5 正式发布,多项重大更新来袭!

喜欢就关注我们吧&#xff01;近日&#xff0c;Kubernetes 管理平台 Rancher 2.5 正式发布&#xff0c;官方公布了在 Rancher 2.5 中的多项重大更新&#xff0c;包括全新的安装体验、针对边缘集群的大规模 GitOps 以及 EKS 集群的全生命周期管理。具体更新信息如下&#xff1a;…

leetcode491. 递增子序列(树层去重魔改版)

一:题目 二:上码 class Solution {/**思路:1.这里已经指明了不允许有重复的&#xff0c;那么树层去重 树枝去重(以前用过的元素不再使用)2.坑:这里不能用 传统的树层去重了 因为我们无法排序了3.这里给出的解决办法是 是利用 hashmap,对每个数出现的频率进行统计如果其频率…

数据结构与算法专题——第十二题 Trie树

今天来聊一聊Trie树&#xff0c;Trie树的名字有很多&#xff0c;比如字典树&#xff0c;前缀树等等。一&#xff1a;概念 下面有and,as,at,cn,com这几个关键词&#xff0c;构建成 trie 树如下。从上面图中&#xff0c;应该可以或多或少的发现一些好玩的特性。根节点不包含字符&…

leetcode46. 全排列

一:题目 二:上码 class Solution {/**1.全排列问题,我们的横向都是从0开始不再是st了 因为我们用到前面已经使用过的元素单是在纵向递归当中我们不能使用重复的元素&#xff0c;这里我们用used来去重。*/private List<List<Integer>> ans new ArrayList<>(…

leetcode47. 全排列 II

一:题目 二:上码 class Solution {private List<List<Integer>> ans new ArrayList<>();private List<Integer> path new ArrayList<>();private boolean[] used;public void getAns(int[] nums,boolean[] used) {if (path.size() nums.leng…

golang项目目录推荐

序言 逛GitHub的时候发现有个4.5k对goalng项目结构的推荐的项目&#xff0c;这里就简单的推荐下 文件目录 /cmd 项目主要的应用程序。 对于每个应用程序来说这个目录的名字应该和项目可执行文件的名字相匹&#xff08;例如&#xff0c;/cmd/myapp&#xff09;。不要在这个…

C# 很少人知道的科技

本文来告诉大家在C#很少有人会发现的科技。即使是工作了好多年的老司机也不一定会知道这些科技&#xff0c;如果觉得我是在骗你&#xff0c;那么请看看本文的内容。原本最初 C# 的设计是简单和高效开发的&#xff0c;在经过了这么多年众多公司和开发者的努力下&#xff0c;整个…

Typescript前端接口联调自动化的探究与实践

源宝导读&#xff1a;Web应用程序一般都是前后端分离的基本架构&#xff0c;而前后端很可能分别是两拨人分别开发&#xff0c;前后端的接口连调成为高频沟通的对象&#xff0c;开发内耗最大的也在这个环节。本文将分享如何基于OpenAPI将前后端接口协议标准化和自动化&#xff0…

leetcode51. N 皇后(java详解)

一:题目 二:上码 class Solution {/**思路:1.先说我们选用的数据结构;我们是选取的是List<List<string>> ans 来存每次的结果;我们在创建这个二维矩阵的时候用的是char的二维数组,那么的话等到我们得到一种可行解的时候 将char的二维数组每一行转换成 String 并存…

程序员如何跨越35岁危机?这篇给点干货建议!

职场&认知洞察 丨 作者 / findyi这是findyi公众号的第83篇原创文章这两天在我的读者群里做了一个职业小调研&#xff0c;发现关注我公众号的70%以上都是程序员。毕竟程序员吸引程序员&#xff0c;这也算猿粪吧&#xff0c;哈哈。这个小调研也引发大家对程序员行业的激烈探讨…

leetcode455. 分发饼干

一:题目 二:上码 class Solution {public int findContentChildren(int[] g, int[] s) {int ans 0;int gIndex 0;int sIndex 0;Arrays.sort(g);Arrays.sort(s);while (gIndex < g.length && sIndex < s.length) {if (s[sIndex] > g[gIndex]) gIndex; //只…

写了多年代码,你会 StackOverflow 吗

写了多年代码&#xff0c;你会 StackOverflow 吗Intro准备写一个傻逼代码的系列文章&#xff0c;怎么写 StackOverflow 的代码&#xff0c;怎么写死锁代码&#xff0c;怎么写一个把 CPU 跑满&#xff0c;怎么写一个 OutOfMemory 的代码。今天主要来看 StackOverflow&#xff0c…

C#实现迭代器

迭代器模式&#xff08;Iterator&#xff09;&#xff0c;提供一种方法顺序访问一个聚合对象中的各种元素&#xff0c;而又不暴露该对象的内部表示。C#中使用IEnumerator接口实现&#xff0c;Java中使用Iterator接口实现&#xff0c;其中原理都差不多&#xff0c;下面我就用C#代…