RLinkの基本
Rは,統計的な計算とグラフィックスのためのプログラミング言語およびソフトウェア環境である.Rはオープンソースプロジェクトで,多数の人の努力により生まれたものである.Rについての詳細は,http://www.r-project.orgを参照されたい.
RLinkは,Rの機能にリンクするためにJLinkとRJava/JRI Javaライブラリを使うWolframシステムアプリケーションである.これを使うと,ユーザはWolfram言語とRの間でデータをやり取りし,R言語コードをWolfram言語内部から実行することができる.
このチュートリアルは,RLinkでどのようなことが可能であるかについてと典型的なRLinkのワークフローについての短い説明を提供するものである.RLinkについてのより詳しい説明は,「RLinkユーザガイド」,「RLinkの関数」,「RLinkにおけるR言語データの型」のチュートリアル,および「RLinkの参照」にリストされているRLink APIの個々の関数についてのドキュメントページを参照されたい.
典型的なワークフロー
Needs["RLink`"]InstallR[]これでアプリケーションが使えるようになった.ワークフローには通常,データをWolfram言語からRに送信し,R言語コードを実行して,結果をWolfram言語に返すという3つのステップの反復が含まれる.以下では,典型的なRLinkのワークフローを短いが濃縮した形で見ていく.
最初の例として,数をRに送り,それが奇数か偶数かを見極めさせてみよう.まず数を選ぶ.
num = RandomInteger[15]RSet["rnum", num]REvaluate["rnum %% 2 == 0"]RSetがデータをRに送って,これをRのワークスペースの変数(あるいは式)に割り当て, REvaluateがR言語コードの文字列を評価して,その結果をWolfram言語に返す.REvaluateは,コードを評価してその結果を返すので,上で述べた3つのステップの最後の2ステップを組み合せるものである.
結果はListでラップされている.これは,Rの視点から見ると,この結果が単一の論理要素を持つベクトルであるからである.
1つの数の代りに数のリストについてテストを行う場合でも,そのプロセスはほとんど変わらない.R関数の多くは自然にベクトル化されるからである.
nums = RandomInteger[15, 5]RSet["rnums", nums];
REvaluate["rnums %% 2 == 0"]より効率化されたシンタックスでR関数を呼び出すには,RFunctionを使う.これを使うと,上の例でもより簡潔な解が出され,大域変数を導入するステップが不要となる.
RFunction["function(x) x %% 2 == 0"][nums]型の変換と式の内部形式
Needs["RLink`"]
InstallR[]nums = RandomInteger[15, 5]もとの数も残しておかなければならない場合には,もう少し高機能のものが得られる.
result = RFunction["function(x) lapply(x,function(y) list(y,y %% 2 == 0))"][nums]Wolfram言語では,同じ操作を行うコードは以下のようになり,より簡単な構造を持つリストを生成する.
{#, EvenQ[#]}& /@ numsこの例から,RとWolfram言語の型のシステムの違いが分かる.返されたのはリストのリストであり,それぞれの部分リストには,一要素の整数べくろる(もとの数)と一要素の論理ベクトル(テスト述語の値)という2つの要素が含まれる.
ToRForm関数を使って,データの RLink の内部表現を見ることができる.データはWolfram言語からの入力データでも,Rから得た結果でもよい.この場合は,結果の構造についての上の記述を確かめることができる.
ff = ToRForm[result]これは,resultに保存される式の内部形式であり,RLinkはこれを使ってRに送るデータと返されるデータを交信する.この形式は,短縮形と同じようにRSet,RFunction,REvaluateで使うことができる.しかしほとんどの場合この形式は,ずっと使いにくい.
FromRForm関数を使って逆の変換を行うこともできる.
FromRForm[ff]実は短縮形での式の構造は簡略することができる.例えば,結果の内部リストを平坦化しても,RLink はこれを正しく解釈する.
simple = Flatten[result, {{1}, {2, 3}}]ToRForm[simple]RLinkの型の自動認識が曖昧である場合がたまにある.この中で注目すべき場合に,同じネイティブな型の要素のリストを構築したい場合がある.このような場合には,デフォルトではリストはベクトルであると解釈される.リストの解釈を強制的に行うことは可能であり,その詳細はRListについてのドキュメントページ,および「データ型」のセクションをご覧になられたい.
自分のR関数を書く
RLinkを使うと,R言語の1行だけのコマンドに制約されない操作を行うことができる.次の例を使ってこのことを見てみよう.Wolfram言語スタイルのSplit関数をRで実装して,ベクトルについて操作を行う.
Needs["RLink`"]
InstallR[]REvaluate["vsplit <- function(vec,test){
result <-list();
current <- list(vec[1]);
for(i in 2:length(vec)){
if(test(vec[i-1],vec[i])){
current <- c(current,vec[i])
}else{
result <- c(result,list(unlist(current)))
current <- list(vec[i])
}
}
if(length(current) != 0){
result <- c(result,list(unlist(current)))
}
return(result)
};"]セミコロンが使われていることに注意する.セミコロンは通常,出力,およびRからWolfram言語への関連データの転送を非表示にするために使われる.
これをテストする.まず,連続実行の尤度を持つ乱数を作成する.
runs = RandomInteger[3, 15]RFunction["function(x) vsplit(x,function(fst,sec) fst == sec)"][runs]Wolfram言語プログラムを使ってまったく同じ操作を行った場合である.
Function[x, Split[x, Function[{fst, sec}, fst == sec]]][runs]Rも RLink も無名関数をサポートするので,Rのワークスペースで定義する関数に与える必要はない.特に次のように定義することもできる.
vsplit = RFunction["function(vec,test){
result <-list();
current <- list(vec[1]);
for(i in 2:length(vec)){
if(test(vec[i-1],vec[i])){
current <- c(current,vec[i])
}else{
result <- c(result,list(unlist(current)))
current <- list(vec[i])
}
}
if(length(current) != 0){
result <- c(result,list(unlist(current)))
}
return(result)
}"]vsplit[runs, RFunction["function(fst,sec) fst == sec"]]関連するガイド
-
▪
- RLink
関連するテクニカルノート
-
▪
- RLinkの参照 ▪
- RLinkユーザガイド ▪
- アプリケーションの構造 ▪
- RLinkの関数