この前、Rを外部から実行するっていうの書いたけど、C#から呼ぶためのライブラリが普通にあったので、書き直し。探し方が悪かったかしらね。。。
R.Netっていうのを使う。NuGetからインスコ。「R.NET.Community」っていうのもあるんだけど、何が違うんだろうか?リンク先とかも一緒なんだけど。。。あー、もちろん使う場合は端末にR本体がインストールされてる必要あり。
そしたらとりあえず、呼び出しサンプル。
using RDotNet; static void Main(string[] args) { REngine.SetEnvironmentVariables();//これは省略可。 using (REngine engine = REngine.GetInstance()) { engine.Evaluate("sample.data <- iris"); engine.Evaluate("str(sample.data)"); } Console.WriteLine("おしまい"); Console.ReadLine(); }
↑は呼び方的には公式のチュートリアルのまま。
まず、32bitか64bitでビルド変えないとだめかも。64bitでやる場合はプロジェクトのプロパティ⇒ビルドで「32ビットを優先」のチェックを外さないとだめそうですね。あと、使うR.dllのフォルダも設定が必要。さらに、Rのパスを通してない場合は、実行時に環境変数のPATHにRのパスを追加しておいた方が良さげ。で、色々したのが↓。パスを編集するメソッドはさすがのすたっくおーばーふろーがサンプル。
static void Main(string[] args) { string rpath = SetupPath("R-3.4.2");//インストールしたバージョンを指定 REngine.SetEnvironmentVariables(rpath); using (REngine engine = REngine.GetInstance()) { engine.Initialize();//最近はこれがいるらしい engine.AutoPrint = false;//これ付けないと代入してる式で中身が丸ごと出てきてうざい engine.Evaluate("sample.data <- iris"); engine.Evaluate("str(sample.data)"); } Console.WriteLine("おしまい"); Console.ReadLine(); } public static string SetupPath(string Rversion) { string rDllPath = Environment.Is64BitProcess ? string.Format(@"C:\Program Files\R\{0}\bin\x64", Rversion) : string.Format(@"C:\Program Files\R\{0}\bin\i386", Rversion); //DLLのフォルダが無かったら例外 if (!Directory.Exists(rDllPath)) { throw new DirectoryNotFoundException(string.Format("Not found : {0}", rDllPath)); } var newPath = string.Format("{0}{1}{2}", rDllPath, System.IO.Path.PathSeparator, Environment.GetEnvironmentVariable("PATH")); Environment.SetEnvironmentVariable("PATH", newPath); return rDllPath; }
でだ、ここまでやっても何故だか実行時に「Rlapack.dllがありません」みたいなエラーが出る端末が稀にいる。意味が分からん。どう見てもあるんだけどね。。。プローブ?がおかしいのだろうか。そういう時はとりあえず、実行ファイルと同じフォルダに「Rlapack.dll」をRのインストール先からコピーしてあげると動くようになる。なんだろね。
ほいで、あとは色々な呼び出し。
static void Main(string[] args) { string rpath = SetupPath("R-3.4.2"); REngine.SetEnvironmentVariables(rpath); using (REngine engine = REngine.GetInstance()) { engine.Initialize(); engine.AutoPrint = false; //////////////////////////////////////// //arulesでアソシエーション分析 //////////////////////////////////////// //ライブラリの読み込み engine.Evaluate("library(arules)"); //アソシエーション分析 engine.Evaluate("data(\"Adult\")"); engine.Evaluate("rules <- apriori(Adult,parameter=list(minlen=2, maxlen=4, support=0.5, confidence=0.9))"); //結果のサマリー engine.Evaluate("summary(rules)"); //結果の表示 engine.Evaluate("inspect(rules)"); //RのデータフレームをC#で扱えるデータにする var dd = engine.Evaluate("Adult@itemInfo").AsDataFrame(); //つまみ食い Console.WriteLine(dd[1, 1]); //////////////////////////////////////// //kmeansの結果を取得 //////////////////////////////////////// //irisデータ使う(いつものやつ) engine.Evaluate("iriswk <- iris[1:150, 1:4]"); engine.Evaluate("iriswk.km <- kmeans(iriswk, 2)"); engine.Evaluate("iriswk.km"); engine.Evaluate("iriswk.km$cluster"); var kmlist = engine.Evaluate("iriswk.km$cluster").AsNumeric(); //////////////////////////////////////// //Plotの画像をファイルにはく //////////////////////////////////////// var path = Path.Combine(Path.GetTempPath(), Path.GetTempFileName() + ".png"); string Code = @"plot(1:10, pch=1:10, col=1:10, cex=seq(1, 2, length=10))"; engine.Evaluate(string.Format("png('{0}', {1}, {2})", path.Replace('\\', '/'), 420, 420)); engine.Evaluate(Code); engine.Evaluate("dev.off()"); } Console.WriteLine("おしまい"); Console.ReadLine(); }