R Language
変数の範囲
サーチ…
備考
スコープを持つ最も一般的な落とし穴は、並列化で発生します。すべての変数と関数は、各スレッドで実行される新しい環境に渡されなければなりません。
環境と機能
関数内で宣言された変数は、その関数内でのみ(渡されない限り)存在します。
x <- 1
foo <- function(x) {
y <- 3
z <- x + y
return(z)
}
y
エラー:オブジェクト 'y'が見つかりません
関数に渡されて再割り当てされた変数は上書きされますが、関数内でのみ使用されます 。
foo <- function(x) {
x <- 2
y <- 3
z <- x + y
return(z)
}
foo(1)
x
5
1
関数より上位の環境に割り当てられた変数は、その関数内で渡されることなく存在します。
foo <- function() {
y <- 3
z <- x + y
return(z)
}
foo()
4
サブ関数
渡されることなくローカル環境で定義された変数にアクセスするには、関数内で呼び出された関数(つまり、サブ関数)をその関数内で定義する必要があります。
これは失敗します:
bar <- function() {
z <- x + y
return(z)
}
foo <- function() {
y <- 3
z <- bar()
return(z)
}
foo()
bar()内のエラー:オブジェクト 'y'が見つかりません
これは動作します:
foo <- function() {
bar <- function() {
z <- x + y
return(z)
}
y <- 3
z <- bar()
return(z)
}
foo()
4
グローバルアサインメント
変数は、 <<-
を使用して任意の環境からグローバルに割り当てることができます。 bar()
はy
アクセスできるようになりました。
bar <- function() {
z <- x + y
return(z)
}
foo <- function() {
y <<- 3
z <- bar()
return(z)
}
foo()
4
グローバルな割り当ては避けてください。ラッパー関数を使用するか、別のローカル環境から変数を明示的に呼び出すことが非常に望ましいです。
環境と変数の明示的な割り当て
Rの環境は、明示的に呼び出して名前を付けることができます。変数は、明示的に割り当てられ、それらの環境から呼び出すことができます。
一般的に作成される環境は、 package:base
またはpackage:base
内のサブ環境を囲む環境です。
e1 <- new.env(parent = baseenv())
e2 <- new.env(parent = e1)
変数は、明示的に割り当てられ、それらの環境から呼び出すことができます。
assign("a", 3, envir = e1)
get("a", envir = e1)
get("a", envir = e2)
3
3
e2
はe1
から継承するので、 e1
とe2
両方でa
は3
です。ただし、 e2
内にa
代入してもe1
のa
の値は変更されません。
assign("a", 2, envir = e2)
get("a", envir = e2)
get("a", envir = e1)
3
2
機能終了
on.exit()
関数は、グローバル変数を割り当てる必要がある場合、変数のクリーンアップに便利です。
一部のパラメータ、特にグラフィックスのパラメータは、グローバルにしか設定できません。この小さな関数は、より特殊なプロットを作成する場合によく使用されます。
new_plot <- function(...) {
old_pars <- par(mar = c(5,4,4,2) + .1, mfrow = c(1,1))
on.exit(par(old_pars))
plot(...)
}
パッケージとマスキング
異なるパッケージ内の関数とオブジェクトは同じ名前を持つことがあります。後で読み込まれたパッケージは以前のパッケージをマスクし、警告メッセージが表示されます。名前で関数を呼び出すと、最後に読み込まれたパッケージの関数が実行されます。以前の関数には明示的にアクセスできます。
library(plyr)
library(dplyr)
添付ファイル: 'dplyr'
次のオブジェクトは 'package:plyr'からマスクされています。
整理する、数える、解く、失敗する、IDを変更する、名前を変更する、要約する、要約する
次のオブジェクトは 'package:stats'からマスクされています:
フィルタリング、遅延
次のオブジェクトは 'package:base'からマスクされています:
交差、setdiff、setequal、union
コードを書くとき、常に使用して明示的に関数を呼び出すためのベストプラクティスであるpackage::function()
特にこの問題を回避します。