このページでは,

 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章の日本語訳に取り組みます.

  • 担当者: yy
  • 修正案の取扱い: みなさまからの修正案は, 下記のコメント欄に書いていただければと思います. 修正そのものは (当面は) 担当者が行います.
  • 分担翻訳の取扱い: 期限を区切って, それまでの間は担当者がひととおりの翻訳を行い, その後, 他の方に翻訳の分担をお願いすべきか検討したいと思います (期限: 2003年 8月 31日まで). よろしくお願いします.
  • 注意点: そのまま訳すと意味がわかりにくくなりそうな場合, オリジナル (英文) の表現やレイアウト等を変更しています.
  • 注意点: 訳注は { } で囲って示します.
  • RとS で、SでのMC()の定義の次の段落が尻切れではないでしょうか。 -- hoge? 2003-09-22 (月) 23:23:16
  • 「S では, 」→「S ではつぎのようになります:」のように書き換えればよろしいでしょうか? -- yy? 2003-09-24 (水) 23:10:03

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


3 R と S (R and S)

  • S とは何ですか? (What is S?)
  • S-PLUS とは何ですか? (What is S-PLUS?)
  • R と S の違いは何ですか? (What are the differences between R and S?)
  • R にできて, S-PLUS にできないことはありますか? (Is there anything R can do that S-PLUS cannot?)
  • R-plus とは何ですか? (What is R-plus?)

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 の主要な参考文献にもなっています.

  • Richard A. Becker and John M. Chambers (1984), "S. An Interactive Environment for Data Analysis and Graphics," Monterey: Wadsworth and Brooks/Cole.

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

  • Richard A. Becker, John M. Chambers and Allan R. Wilks (1988), "The New S Language," London: Chapman & Hall.

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

  • John M. Chambers and Trevor J. Hastie (1992), "Statistical Models in S," London: Chapman & Hall.

この書籍はまた "白本 (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 エンジンを表します.

  • レキシカル・スコープ (Lexical scoping)
  • モデル (Models)
  • その他 (Others)

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)

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

  • y を x^3 に回帰させるには, S では lm(y ~ x^3) を用いますが, R では数値ベクトルの累乗を (I() を用いて) 隔離する必要があります. つまり, lm(y ~ I(x^3)) を用いる必要があります.
  • glm ファミリーのオブジェクトは R と S では異なって実装されています. 同一の機能が利用可能ですが, 要素は異なる名前をもっています.
  • オプション na.action は, R ではディフォールトで "na.omit" にセットされますが, S ではセットされません.
  • 項 (terms) オブジェクトが異なる方法で格納されます. S では, 項オブジェクトは属性群を持つ表現式 (expression) ですが, R では属性群を持つモデル式 (formula) です. この属性群は, { S と R で } 同じ名前を持っていますが, ほとんど異なる方法で格納されます. 機能上の重要な相違点は, S では項オブジェクトは添え字可能 (subscriptable) であるのに対して, R では添え字可能ではないということです. このことがどうして問題になるのか分からないのなら, 知る必要はありません.
  • 最後に, R では, 切片を持たないモデルを指定するための y~x-1 の代替方法として y~x+0 を用いることができます. パラメーターをまったく持たないモデルは, y~0 で指定することができます.

3.3.3 その他 (Others)

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

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

  • R では, x がリストならば, x[i] <- NULL および x[ [i] ] <- NULL は指定した要素を x から削除します. これらの最初のもの { x[i] <- NULL } は, no-op であり, S とは非互換です. (注. x[i] <- list(NULL) を用いて, 要素を NULL にセットすることができます.)
  • S では, .Data ディレクトリー内の .First および .Last という名前の関数群を, セッションのぞれぞれいちばん始めと終わりに実行されるように, カスタマイズするのに用いることができます.
    R では, 起動の仕組みは下記の通りです. R は最初に, システムの起動ファイル $R_HOME/library/base/R/Rprofile を読み込みます. それから, コマンド・ライン・オプション --no-site-file が与えられていなければ, サイト用の起動プロファイルを探します. このファイルの名前は, R_PROFILE 環境変数の値から取得されます. その変数がセットされていない場合, ディフォールト値は $R_HOME/etc/Rprofile.site (1.4.0 より前のヴァージョンでは $R_HOME/etc/Rprofile) です. このコードはパッケージ base にロードされます. それから, コマンド・ライン・オプション --no-init-file が与えられていなければ, R は .Rprofile という名前のファイルを, 現在のディレクトリーあるいはこのユーザーのホーム・ディレクトリー内で (この順に) 探し, それをこのユーザーのワークスペースの中に読み込みます. それから (--no-restore が指定されていなければ) .RData があればそこから, このユーザーのワークスペースの保存されたイメージをロードします. 必要ならば, .First() および .Last() を適当な起動プロファイル内に定義しておかなければいけません.
  • R では, T と F は単に TRUE と FALSE にそれぞれセットされている変数にすぎなくて, S のように予約語になっていません. したがって, ユーザーによって上書きすることができます. (これは, たとえば, "T" あるいは "F" のレヴェルを持つ因子があるときに役に立ちます.) したがって, コードを書くときは, つねに, TRUE と FALSE を用いるべきです.
  • R では, dyn.load() は, (たとえば, R CMD SHLIB によって作られるような) 共有オブジェクトだけロードすることができます.
  • R では, attach() は現在のところ, リストおよびデータ・フレームだけに機能し, ディレクトリーには機能しません. (実のところ, attach() は, save() で作られた R のデータ・ファイルにも機能するので, S においてディレクトリーを所属させる (attach) ことに類似します.) また, 1 番目の位置に所属させることはできません.
  • R では, カテゴリー (categories) は存在しません. また, S でも, 現在, 非推奨 (deprecated) になっているので, 今後も R でカテゴリーが存在することは決してありません. 代わりに, 因子 (factors) を使ってください.
  • R では, For() ループは必要ではなく, したがってサポートされません.
  • R における assign() は引数 envir= を用いますが, S における assign() は引数 where= を用います.
  • 乱数発生器が異なっていて, 乱数の種は異なる長さを持ちます.
  • R では整数オブジェクトを int * として C に渡しますが, S では long * として渡します.
  • R には単精度格納モードがありません. しかしながら, ヴァージョン 0.65.1 より, C/FORTRAN サブルーチンとの単精度インターフェイスが存在します.
  • ディフォールトでは, ls() は, 現在の環境 (R の場合) / グローバルの環境 (S の場合) におけるオブジェクトの名前を返します. たとえば,
     x <- 1; fun <- function() {y <- 1; ls()}
    を与えた場合, fun() は, R では "y" を, S では (グローバルの環境の他のオブジェクトの名前と共に) "x" を返します.
  • R は, ゼロ長の (zero-extent) 行列 (および配列, つまり, dim 属性ベクトルのいくつかの要素が 0 になる可能性がある) を考慮します. これは, 空の部分集合についての特別な場合の検査の必要を減らすのに役立つので, 有益な機能であると判断されています. たとえば, x は行列であり, x[, FALSE] は NULL ではないけれども 0 個の列を持つ "行列" であるとします. このようなオブジェクトは, is.null() を用いるのではなく, その length() がゼロになるかどうかチェックすることにより, 検査する必要があります.
  • 名前付きのベクトルは, R ではベクトルとみなされますが, S ではベクトルとみなされません (たとえば, is.vector(c(a = 1:3)) は S では FALSE, R では TRUE を返します).
  • R では, データ・フレームは行列とみなされません. (つまり, DF がデータ・フレームならば, is.matrix(DF) は R では FALSE, S では TRUE を返します).
  • R は, 順序なしの場合にディフォールトで処理対比 (コントラスト) (treatment contrasts) を用いますが, S は Helmert 対比を用います. これは, 処理対比のほうがより自然であるという見解を反映する意図的な違いです.
  • R では, 右辺に相当する置換関数の引数は名前付きの値でなければいけません. たとえば, f(a) <- b は a <- "f<-"(a, value = b) と評価されます. S はつねに最後の引数を (その名前に関わりなく) 取ります.
  • S では, substitute() は, 与えられた表現式における代入のための名前をつぎの 3箇所で探します: そのマッチする呼出しの実際の引数, ディフォールトの引数, ローカルのフレーム (この順に探します). R はローカルのフレーム内だけを探します. なお R では, ある変数が評価されない場合は "予約 (promise)" を用いるという特別なルールがあります. ローカルのフレームは, 実際の引数あるいはディフォールトの表現四季で初期化されるので, R での挙動は, 代入 (assignment) が実行されるまでは, 通常 S と等価です.
  • S では, for() ループにおけるインデクス変数は, そのループの内部に対してローカルです. R では, for() 文が実行される環境に対してローカルです.
  • tapply(simplify=TRUE) は, S ではベクトルを返し, R では (名前付きの dimnames を持つことのできる) 1次元の配列を返します.
  • S(-PLUS) では C ロケールを用いるのに対して, R では現在の OS のロケールを用いて, どの文字が英数字 (alphanumeric) であるか, また, 文字をどのようにソートするかを決定します. これは, R オブジェクトに対する正当な名前の組に影響をおよぼします (たとえば, R ではアクセント付き文字が許されるかもしれません). また, ソートや比較の順序に影響をおよぼします ("aA" < "Bb" は真か偽かというような). ヴァージョン 1.2.0 から, R では Sys.setlocale() 関数によってロケールを (再) 設定できます.
  • S では, missing(arg) は arg が後から変更されても TRUE のままですが, R ではそうではありません.
  • R ヴァージョン 1.3.0 から, data.frame は, (列の) 名前を作る際に, I() をはずします.
  • R では, 文字列 "NA" は文字変数における欠測値として扱われません. 文字変数における欠測値を作るには as.character(NA) を使ってください.
  • R は, 関数呼出しにおいて, 繰り返される形式的引数を認めません.

また, 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
Google
WWW を検索 OKADAJP.ORG を検索
Last-modified: 2015-03-01 (日) 01:15:59 (1727d)