このページでは,

 R FAQ
 Frequently Asked Questions on R
 Version 1.7-27, 2003-07-16
 ISBN 3-901167-51-X
 Kurt Hornik

(http://cran.r-project.org/doc/FAQ/R-FAQ.html ) の第 3章の日本語訳に取り組みます.


R-FAQ 日本語訳全体の目次


3 R と S (R and S)

3.1 S とは何ですか? (What is S?)

S は, データ解析およびグラフィクスのための非常に高いレヴェルの言語および環境です. 1998年, Association for Computing Machinery (ACM) は, S の筆頭設計者である John M. Chambers に Software System Award を授与しました. その受賞理由は,

S システムは人々がデータを分析, 可視化, 操作する方法をいつまでも様変わりさせ...

S は, 洗練され, 広く認められた, 恒久的なソフトウエア・システムであり, 概念的統合性があり, それは John Chambers の洞察力, 趣味の良さ, そして努力の結果です.

S 言語の進化は, John Chambers および共著者たちによる 4冊の書籍で特徴付けられています. これらの書籍は S の主要な参考文献にもなっています.

この書籍はまた "茶本 (Brown Book)" という名前で参照され, 歴史的に興味深いだけです.

この書籍はよく "青本 (Blue Book)" と呼ばれ, 現在 S ヴァージョン 2 として知られているものを紹介しています.

この書籍はまた "白本 (White Book)" と呼ばれ, S ヴァージョン 3 を紹介しています. このヴァージョンでは, S において統計的モデリングを容易にする構造が加えられています.

この "緑本 (Green Book)" は S ヴァージョン 4 について記述されていて, プログラミングの過程の各段階で S の有用性を改良するために, John Chambers によって設計された S の主要な改訂版になっています.

"S の進化の段階 (Stages in the Evolution of S)" に関するより詳しい情報は http://cm.bell-labs.com/cm/ms/departments/sia/S/history.html をご参照ください.

膨大な量の S 用のユーザー寄贈のコードが存在し, CMU の S Repository で入手可能です.

3.2 S-PLUS とは何ですか? (What is S-PLUS?)

S-PLUS は Insightful Corporation が販売する S の付加価値ヴァージョンです. S 言語をベースとして, S-PLUS はさまざまな領域の機能を提供します. たとえば, ロバストな回帰, モダンなノン‐パラメトリック回帰, 時系列解析, 生存分析, 多変量解析, 古典的な統計的検定, 品質管理, グラフィクス・ドライヴァーなど. アドオン・モジュールによって, ウェーブレット解析, 空間統計学, GARCH モデル, および実験計画法についての付加的能力が加えられます.

より詳しい情報については Insightful S-PLUS のページをご参照ください.

3.3 R と S の違いは何ですか? (What are the differences between R and S?)

私たちは, S のことを 3種類の現行の実装, つまり "エンジン", を持つ言語とみなすことができます. それらは, "古い S エンジン" (S ヴァージョン 3; S-PLUS 3.x および 4.x), "新しい S エンジン" (S ヴァージョン 4; S-PLUS 5.x 以降), そして R です. このような理解を踏まえると, "R と S の違い" について尋ねることは, 実際には, S 言語の R での実装の詳細, つまり R と S のエンジンの違い, について尋ねることになります.

このセクションの残りでは, "S" は, S 言語ではなく, S エンジンを表します.

3.3.1 レキシカル・スコープ (Lexical scoping)

S 言語の他の実装に反し, R は Scheme の評価モデルを採用しています.

この違いは関数内で自由変数が生じるときに明白になります. 自由変数とは, (その関数の引数リストの中に現れる) 正式なパラメーターでもなく, (その関数本体の中で変数への代入によって生成される) ローカル変数でもない変数です. S が (C のように) ディフォールトで静的スコープを用いるのに対して, R は (Scheme のように) レキシカル・スコープを採用しています. このことが意味するのは, 自由変数の値が, S ではグローバル変数の組によって決定されますが, R ではその関数が作られた時点で効力のあったバインディングによって決定されるということです.

つぎの関数について考察しましょう:

 cube <- function(n) {
   sq <- function() n * n
   n * sq()
 }

S の場合, 変数 n をグローバルに定義しないかぎり, sq() は変数 n について "知る" ことはありません.

 S> cube(2)
 Error in sq():  Object "n" not found
 Dumped
 S> n <- 3
 S> cube(2)
 [1] 18

R の場合, cube() が呼び出されたときに作られた "環境" の中を見ます:

 R> cube(2)
 [1] 8

もっと "興味深い" 実世界の問題として, ある (連続) 分布から抽出したサイズ n の標本に基づく r-番目の順序統計量の密度関数を返す関数を書くことを想定しましょう. 単純化のために, この分布の cdf と pdf の両方を明示的な引数として用います. (Luke Tierney によって, さまざまな投稿の中からまとめられた実行例.)

call() に関する S-PLUS の文書では基本的につぎを勧めています:

 dorder <- function(n, r, pfun, dfun) {
   f <- function(x) NULL
   con <- round(exp(lgamma(n + 1) - lgamma(r) - lgamma(n - r + 1)))
   PF <- call(substitute(pfun), as.name("x"))
   DF <- call(substitute(dfun), as.name("x"))
   f[[length(f)]] <-
     call("*", con,
       call("*", call("^", PF, r - 1),
         call("*", call("^", call("-", 1, PF), n - r),
           DF)))
   f
 }

かなりトリッキーですよね? このコードは, S では関数群は最後の引数が関数の本体になっている特別なモードのリストにすぎないという事実を利用しています. そのため, このコードは R では機能しません (機能するようにすることは可能ですが).

substitute() を大いに利用して, S と R の両方で機能すると思われるヴァージョンは,

 dorder <- function(n, r, pfun, dfun) {
   con <- round(exp(lgamma(n + 1) - lgamma(r) - lgamma(n - r + 1)))
   eval(substitute(function(x) K * PF(x)^a * (1 - PF(x))^b * DF(x),
     list(PF = substitute(pfun), DF = substitute(dfun),
      a = r - 1, b = n - r, K = con)))
 }

(S では eval() は必要ありません).

しかしながら, R ではずっと簡単な解があります:

 dorder <- function(n, r, pfun, dfun) {
   con <- round(exp(lgamma(n + 1) - lgamma(r) - lgamma(n - r + 1)))
   function(x) {
     con * pfun(x)^(r - 1) * (1 - pfun(x))^(n - r) * dfun(x)
   }
 }

これは "自然な" 実装であるように見えます. これが機能するのは, その返される関数の中の自由変数を, 定義している環境の中で探すことができるからです (これがレキシカル・スコープです).

注. あなたがほんとうに必要なものは, 関数閉包 (クロージャー), つまり関数を評価するために必要とされる変数のバインディングをすべて伴っている, 関数の本体です. 上記のヴァージョンではその値の関数の中の自由変数が変更されないので, 関数 MC() ("make closure" の略) の中にその閉包操作を抽出 (abstract out) すれば, 実際には S でも同様に使うことができます:

 dorder <- function(n, r, pfun, dfun) {
   con <- round(exp(lgamma(n + 1) - lgamma(r) - lgamma(n - r + 1)))
   MC(function(x) {
     con * pfun(x)^(r - 1) * (1 - pfun(x))^(n - r) * dfun(x)
   },
   list(con = con, pfun = pfun, dfun = dfun, r = r, n = n))
 }

この閉包操作について適切な定義を与えれば, これは R と S の両方で機能します. それに, substitute/eval を用いる方法よりも (あるいは, R と S の両方でもちろん可能なように, 評価フレームに明示的にアクセスすることによってディフォールトのスコープの法則を覆す方法よりも) ずっと "きれい" です.

R では, MC() は単純に

 MC <- function(f, env) f

となります (レキシカル・スコープ!). S ではつぎのようになります:

 MC <- function(f, env = NULL) {
   env <- as.list(env)
   if (mode(f) != "function")
     stop(paste("not a function:", f))
   if (length(env) > 0 && any(names(env) == ""))
     stop(paste("not all arguments are named:", env))
   fargs <- if(length(f) > 1) f[1:(length(f) - 1)] else NULL
   fargs <- c(fargs, env)
   if (any(duplicated(names(fargs))))
     stop(paste("duplicated arguments:", paste(names(fargs)),
       collapse = ", "))
   fbody <- f[length(f)]
   cf <- c(fargs, fbody)
   mode(cf) <- "function"
   return(cf)
 }

同様に, たいていの最適化ルーチン (あるいはゼロを発見するルーチン) は, 最適化されるべき引数がいくつか必要であり, その他にデータに依存するけれども最適化に関して固定されるパラメーターを持っています. R のスコープの法則では, これは些細な問題です; 単に, 同一の環境で必要な定義を持つ関数を作成すれば, スコープがその面倒を見てくれます. S では, 関数と最適化に余分のパラメーターを加えて,

レキシカル・スコープでは, 関数閉包を用いることと, 局所的な状態を保持することができます. R のプロンプトで demo("scoping") とタイプすることで, 単純な実行例 (Abelson and Sussman { Structure and Interpretation of Computer Programs (2nd ed), 3.4 Concurrency: Time Is of the Essence } からの引用) が得られます. つぎの文献に, さらに詳しい情報が与えられています: 標準的な R の参考文献 "R: A Language for Data Analysis and Graphics" (R にはどんな文書がありますか? (What documentation exists for R?) 参照) および Robert Gentleman and Ross Ihaka (2000), "Lexical Scope and Statistical Computing", Journal of Computational and Graphical Statistics, 9, 491-508.

レキシカル・スコープはまた, さらに重要な違いを暗示します. S がすべてのオブジェクトをどこかのディレクトリー (通常, 現在のディレクトリー下の .Data) 内の別々のファイルに格納するのに対して, R はそうしません. R ではすべてのオブジェクトが内部的に格納されます. R は, 起動時に非常に大きなメモリーの断片をつかみ取り, オブジェクトを格納するのに利用します. R はこのメモリーの断片について自分自身のメモリー管理を行います. シンボル/値のペアについてすべての関係のある "環境" を外部的に保持するのは不可能であるから, あらゆるものをメモリーに持つことが必要です. この違いはまた, R を S よりも高速にするように見えます.

良くない点は, もしも R がクラッシュすると, 現在のセッションについての作業すべてを失ってしまうことです. メモリーの "イメージ" (任意の時点での R の内部的なメモリーに格納された関数およびデータ) を保存・格納することは, サイズが大きいときはとくに, 遅くなるかもしれません. S ではこのようなことは起こりません. というのは, あらゆるものをディスクのファイルに保存しているので, クラッシュが起こってもファイルには影響がないからです. (実のところ, S の開発者たちは, 単にレキシカル・スコープを提供するために, 永続的な格納という彼らのアプローチを変更するのはあまりにも代償が大きすぎると感じた, と推測できるかもしれません.) そのような訳で, 重要な作業を行っているときは, もしものクラッシュに備えて, 頻繁に保存することに注意を払っても良いかもしれません (自分のワークスペースを保存するには? (How can I save my workspace?) 参照). その他の可能な方法として, あなたが実行しているセッションのログを取ること, つまり, あなたが実行した R のコマンドを source() を用いて読み込むことのできるテキスト・ファイルに格納させることです.

注意: もしも R を Emacs の中から実行するならば (R と Emacs (R and Emacs) 参照), 対話バッファー (interaction buffer) の内容をファイルに保存することができ, ess-transcript-mode を用いて都合良く操作することができます. 同様に, 使用したすべての関数とデータのコピーを保存することができます.

3.3.2 モデル (Models)

モデリングのコードにいくつかの違いがあります. たとえば,

3.3.3 その他 (Others)

レキシカル・スコープとそれが及ぼす影響以外は, R は, 青本および白本 (Blue and White Books) における S 言語の定義に可能なかぎり従っていて, そのため, ほんとうに S の "実装" になっています. S の挙動が "きれいではない" とみなされる箇所では, いくつかの意図的な違いがあります. 一般に, その {意図的な違いの} 根拠は, R がプログラミングのエラーを検出するのに役立つべきであり, 同時に, 可能なかぎり S と互換になっていることです.

いくつかの既知の相違点は下記のものです.

また, R で不足している, あるいは不正確なコードから生じる, 意図しない相違点もあります. 開発者たちは, あなたが見つけた欠陥を (あなたが見たままの相違点を完全に文書化するレポートで) 知らせてもらえると感謝します. もちろん, あなた自身でその変更点を実装し, それがきちんと機能することを確認してくれるなら, 有益でしょう.

3.4 R にできて, S-PLUS にできないことはありますか? (Is there anything R can do that S-PLUS cannot?)

R 上で実行できるほとんどのものには, ほんの少しの労力で S-PLUS に移植できるソース・コードがあるので, R 上で実行できて S-PLUS 上でできないことはそれほど多くないでしょう. (注. けれども, レキシカル・スコープを用いることで物事をかなり単純にするかもしれません.)

R は, S-PLUS にないいくつかのグラフィクス機能を提供します. たとえば, 線の形式についてのより細かい取扱い, より便利な色の取扱い (パレットを用いる), 色のガンマ補正, そしていちばん重要なことには, テキストのプロットでの数式注釈機能 (TeX の構成を連想させる入力表現を用いる) など. plotmath についての help ページをご参照ください. そこに, 印象的なオンラインの実行例があります. さらなる詳細については, つぎの書籍で見つけることができます: Ross Ihaka (2000), "An Approach to Providing Mathematical Annotation in Plots", Journal of Computational and Graphical Statistics, 9, 582-599.

3.5 R-plus とは何ですか? (What is R-plus?)

そのようなものはありません.


{ 3章おわり }

最終更新日: 2003-08-20 (水) 23:23:23


トップ   編集 凍結 差分 バックアップ 添付 複製 名前変更 リロード   新規 一覧 検索 最終更新   ヘルプ   最終更新のRSS
Last-modified: 2023-03-25 (土) 11:19:17