30

R 名前空間は、関連付けられたパッケージ内のすべての関数の直接の環境として機能します。言い換えると、bar()パッケージfooの関数が別の関数を呼び出すとき、R エバリュエーターは、最初に 内<environment: namespace:foo>、次に 、"imports.foo"<environment: namespace:base>という<environment: R_GlobalEnv>ように、 と入力して返された検索リストを下方向に別の関数を検索しますsearch()

名前空間の優れた側面の 1 つは、パッケージをより良い市民のように振る舞わせることができる<environment: namespace:foo>ことimports:fooです。(b) fooからインポートする他のパッケージへ。または (c) のような完全修飾関数呼び出しを介して。foo:::bar()

と、最近まで思っていたのですが…

振る舞い

この最近の SO の質問では、パッケージの名前空間に十分に隠されている関数が、一見無関係な関数の呼び出しによって見つかったというケースが強​​調されました。

group <- c("C","F","D","B","A","E")
num <- c(12,11,7,7,2,1)
data <- data.frame(group,num)

## Evaluated **before** attaching 'gmodels' package
T1 <- transform(data, group = reorder(group,-num))

## Evaluated **after** attaching 'gmodels
library(gmodels)
T2 <- transform(data, group = reorder(group,-num))

identical(T1, T2) 
# [1] FALSE

その直接の原因

@Andrie は、gmodelsがパッケージ gdata からインポートれることを指摘して、元の質問に答えました。最初のものは によって計算され、2 番目のものは によって計算されるため、とは異なります。reorder.factortransform()T1T2stats:::reorder.default()gdata:::reorder.factor()

私の質問

上記の への呼び出しtransform(data, group=reorder(...))で、ディスパッチ メカニズムがreorder検出されてから にディスパッチされるのはgdata:::reorder.factor()どうしてでしょうか。

(回答には、 statsおよびbaseパッケージの関数を含む呼び出しからgdataの一見よく隠されているメソッドにつながるスコープ規則の説明が含まれている必要があります。)


さらに役立つ可能性のある詳細

  1. どちらgdata:::reorder.factorgdataパッケージ全体もgmodelsによって明示的にインポートされません。gmodelsNAMESPACEファイルのimport*ディレクティブは次のとおりです。

    importFrom(MASS, ginv)
    importFrom(gdata, frameApply)
    importFrom(gdata, nobs)
    
  2. reorder()またはtransform()in <environment: namespace:gmodels>、または inのメソッドはありません"imports:gmodels"

    ls(getNamespace("gmodels"))
    ls(parent.env(getNamespace("gmodels")))
    
  3. gmodels をデタッチしても の動作は元に戻りませんreorder():gdata:::reorder.factor()それでもディスパッチされます:

    detach("package:gmodels")
    T3 <- transform(data, group=reorder(group,-num))
    identical(T3, T2)
    # [1] TRUE
    
  4. reorder.factor()ベース環境の S3 メソッドのリストに保存されていません。

    grep("reorder", ls(.__S3MethodsTable__.))
    # integer(0)
    

ここ数日の R チャット スレッドには、いくつかの追加のアイデアが含まれています。Andrie、Brian Diggs、Gavin Simpson に感謝します。この質問の詳細。

4

1 に答える 1

18

あなたの質問を正しく理解しているかどうかはわかりませんが、要点はgroup文字ベクトルでありdata$group、因子です。

付けた後gmodels、コールのreorder(factor)呼び出しgdata:::reorder.factor。だから、それをreorder(factor(group))呼び出します。

ではtransform、関数は最初の引数の環境内で評価されるため、 inT2 <- transform(data, group = reorder(group,-num))groupfactor です。

更新しました

library読み込み済みの名前空間にインポート パッケージをアタッチします。

> loadedNamespaces()
 [1] "RCurl"     "base"      "datasets"  "devtools"  "grDevices" "graphics"  "methods"  
 [8] "stats"     "tools"     "utils"    
> library(gmodels) # here, namespace:gdata is loaded
> loadedNamespaces()
 [1] "MASS"      "RCurl"     "base"      "datasets"  "devtools"  "gdata"     "gmodels"  
 [8] "grDevices" "graphics"  "gtools"    "methods"   "stats"     "tools"     "utils"    

念のため、reorderジェネリックは次の場所にありnamespace:statsます。

> r <- ls(.__S3MethodsTable__., envir = asNamespace("stats"))
> r[grep("reorder", r)]
[1] "reorder"            "reorder.default"    "reorder.dendrogram"

そして、詳細については

の呼び出しはreorder、2 つの env で S3generics を検索します。

見る?UseMethod

最初にジェネリック関数が呼び出される環境で、次にジェネリック関数が定義されている環境 (通常は名前空間) の登録データベースで。

次に、loadNamespaceS3 関数を名前空間に登録します。

したがって、あなたの場合、library(gmodels)-> loadNamespace(gdata)-> registerS3Methods(gdata).

この後、次の方法で見つけることができます。

> methods(reorder)
[1] reorder.default*    reorder.dendrogram* reorder.factor*    

   Non-visible functions are asterisked

ただし、reorder.factorは検索パスに添付されていないため、直接アクセスすることはできません。

> reorder.factor
Error: object 'reorder.factor' not found

おそらくこれがシナリオ全体です。

于 2012-06-12T22:38:49.590 に答える