2016-01-04 9 views
6

セグメント化されたパッケージを使用していて、関数内からdavies.test()を呼び出すときに問題が発生しました。完璧に動作し、セグメント化された回帰が2つの統計学的に異なる傾きを有していることを示している囲む環境からデータにアクセスする機能

library(segmented) 

data = data.frame(x = 1:21, y = c(10:1, 0:10)) 
fit = lm(y ~ x, data = data) 
fit.seg = segmented(fit, seg.Z = ~ x) 
davies.test(fit.seg, seg.Z = ~ x, alternative = "greater") 

は、次のような状況を考えてみましょう。そして、それが正常に動作します

testit <- function() { 
    data = data.frame(x = 1:21, y = c(10:1, 0:10)) 
    fit = lm(y ~ x, data) 
    fit.seg = segmented(fit, seg.Z = ~ x) 
    davies.test(fit.seg, seg.Z = ~ x, alternative = "greater")$p.value 
} 
testit() 

...

をしかし、私は地球環境からfitを削除した場合、それは失敗します。

今、私はこのような関数にそのすべてをパッケージた場合。

> rm(fit) 
> testit() 
Error in eval(expr, envir, enclos) : object 'fit' not found 

問題はdavies.testfitでカプセル化されたデータにアクセスしようとしているような方法であると思われる:それは(この場合はtestit関数である)囲みスコープにfitを探していないようですグローバルスコープに直接スキップします。

この問題は、Rのスコープ規則を使用して微妙に関係していると思います。この辺のケースでパッケージ作者に迷惑をかけないようにするための迅速な修正を見つけることができれば、それは素晴らしいことです。

ありがとう、 Andrew。

答えて

4

##と記された行を挿入してみてください。変更されたtestitが実行されたときに出力されるpvalueが同じであるため、必要に応じて十分である場合に表示される警告に示されているように、これは考慮されていません。これはもちろん、パッケージ内のバグであり、パッケージのメンテナーにそれを修正するかどうかを尋ねるのが最善の方法です。

library(segmented) 
testit <- function() { 
    data = data.frame(x = 1:21, y = c(10:1, 0:10)) 
    fit = lm(y ~ x, data) 
    fit.seg = segmented(fit, seg.Z = ~ x) 
    environment(davies.test) <- environment() ## 
    davies.test(fit.seg, seg.Z = ~ x, alternative = "greater")$p.value 
} 
testit() 

与える:

[1] 0.01858149 
Warning message: 
In summary.lm(object) : essentially perfect fit: summary may be unreliable 
+0

ありがとうございます。この警告は、テストデータが構築される方法によるものです。関連する問題ではありません。 – DataWookie

3

グローバル変数にする必要はありません。問題は実際にはであり、davies.testではありません。 fitが見つかりません。

あなたは、呼び出し元の関数の環境を含め、あらゆる環境でfitを見つけるためにdynGetを使用することができます。

testit <- function() { 
    data = data.frame(x = 1:21, y = c(10:1, 0:10)) 
    fit = lm(y ~ x, data) 
    fit.seg = segmented(dynGet("fit"), seg.Z = ~ x) 
    davies.test(fit.seg, seg.Z = ~ x, alternative = "greater")$p.value 
} 
testit() 

あなたが意図したとおりに動作しなければならないこと。

異なる環境に複数の変数fitがある場合は、get?getを参照)を使用して、取得する環境を指定します。 dynGetは「どこでも見て、最初に戻る」という怠惰なバージョンです。

+1

問題は、 'davis.test'内の評価です。 'traceback'の出力を参照してください。 – Roland

+0

素晴らしい!それはトリックです。ありがとうございました。 – DataWookie

+1

'segmented(get(" fit "、sys.frame(1))、seg.Z =〜x)' これは、他の場所で可能な名前空間の衝突を避けるために、 dynG​​et() '。 –

1

私はsegmentedの作者に連絡し、彼は速やかに答えました。明確にするため

testit <- function() { 
    data = data.frame(x = 1:21, y = c(10:1, 0:10)) 
    fit = lm(y ~ x, data) 
    davies.test(fit, seg.Z = ~ x, alternative = "greater")$p.value 
} 

しかし、それが必要:彼は、元の問題に提案されている別の解決策は、

testit <- function() { 
    data = data.frame(x = 1:21, y = c(10:1, 0:10)) 
    fit = lm(y ~ x, data) 
    fit.seg = segmented(fit, seg.Z = ~ x) 
    fit.seg$call$obj<-fit 
    davies.test(fit.seg, seg.Z = ~ x, alternative = "greater")$p.value 
} 

だろうしかし、彼はまた、次のようにlmオブジェクトが実際にdavies.test()に直接渡されるべきであることを指摘しましたこれらの2ビットのコードは、異なることを行うことに注意してください。最初のフラグメントは、秒()のbrが存在するかどうかを確認しながら、2番目のフラグメントは実際に私の本来の目的eak。

関連する問題