Variabel global dan lokal dalam R

126

Saya seorang pemula untuk R, dan saya cukup bingung dengan penggunaan variabel lokal dan global dalam R.

Saya membaca beberapa posting di internet yang mengatakan apakah saya menggunakan =atau <-saya akan menetapkan variabel di lingkungan saat ini, dan dengan <<-saya dapat mengakses variabel global ketika berada di dalam suatu fungsi.

Namun, seperti yang saya ingat di C ++ variabel lokal muncul setiap kali Anda mendeklarasikan variabel di dalam tanda kurung {}, jadi saya ingin tahu apakah ini sama untuk R? Atau hanya untuk fungsi - fungsi dalam R yang kita punya konsep variabel lokal.

Saya melakukan sedikit percobaan, yang tampaknya menyarankan bahwa hanya kurung saja tidak cukup, apakah saya mendapatkan kesalahan?

{
   x=matrix(1:10,2,5)
}
print(x[2,2])
[1] 4
Vokram
sumber
Beberapa kode untuk dijalankan sebagai tambahan atas jawaban-jawaban ini: globalenv(); globalenv() %>% parent.env; globalenv() %>% parent.env %>% parent.env,…
isomorphismes
@isomorfisma Error: could not find function "%>%",. Apakah itu bentuk tugas lain?
Aaron McDaid
1
Utas yang relevan di R-help: Apa yang dimaksud dengan operator "<< -"? .
Henrik
1
@AaronMcDaid Hai, maaf karena tidak merespons lebih cepat! Itu dari require(magrittr). Ini adalah cara menerapkan fungsi di sebelah kanan ( x | f1 | f2 | f3) alih-alih di sebelah kiri ( f3( f2( f1( x ) ) )).
isomorphismes

Jawaban:

153

Variabel yang dideklarasikan di dalam suatu fungsi adalah lokal untuk fungsi itu. Misalnya:

foo <- function() {
    bar <- 1
}
foo()
bar

memberikan error berikut: Error: object 'bar' not found.

Jika Anda ingin membuat barvariabel global, Anda harus melakukan:

foo <- function() {
    bar <<- 1
}
foo()
bar

Dalam hal barini dapat diakses dari luar fungsi.

Namun, tidak seperti C, C ++ atau banyak bahasa lain, tanda kurung tidak menentukan ruang lingkup variabel. Misalnya, dalam cuplikan kode berikut:

if (x > 10) {
    y <- 0
}
else {
    y <- 1
}

ytetap dapat diakses setelah if-elsepernyataan.

Seperti yang Anda katakan, Anda juga dapat membuat lingkungan bersarang. Anda dapat melihat kedua tautan ini untuk memahami cara menggunakannya:

  1. http://stat.ethz.ch/R-manual/R-devel/library/base/html/environment.html
  2. http://stat.ethz.ch/R-manual/R-devel/library/base/html/get.html

Di sini Anda memiliki contoh kecil:

test.env <- new.env()

assign('var', 100, envir=test.env)
# or simply
test.env$var <- 100

get('var') # var cannot be found since it is not defined in this environment
get('var', envir=test.env) # now it can be found
betabandido
sumber
136

<- melakukan penugasan di lingkungan saat ini.

Saat Anda berada di dalam fungsi R menciptakan lingkungan baru untuk Anda. Secara default itu mencakup segala sesuatu dari lingkungan di mana ia dibuat sehingga Anda dapat menggunakan variabel-variabel itu juga, tetapi apa pun yang Anda buat tidak akan ditulis ke lingkungan global.

Dalam kebanyakan kasus <<-akan menetapkan variabel yang sudah ada di lingkungan global atau membuat variabel di lingkungan global bahkan jika Anda berada di dalam suatu fungsi. Namun, tidak sesederhana itu. Apa yang dilakukannya adalah memeriksa lingkungan induk untuk variabel dengan nama yang menarik. Jika tidak menemukannya di lingkungan induk Anda, ia pergi ke induk dari lingkungan induk (pada saat fungsi dibuat) dan terlihat di sana. Itu terus ke atas ke lingkungan global dan jika tidak ditemukan di lingkungan global itu akan menetapkan variabel di lingkungan global.

Ini mungkin menggambarkan apa yang sedang terjadi.

bar <- "global"
foo <- function(){
    bar <- "in foo"
    baz <- function(){
        bar <- "in baz - before <<-"
        bar <<- "in baz - after <<-"
        print(bar)
    }
    print(bar)
    baz()
    print(bar)
}
> bar
[1] "global"
> foo()
[1] "in foo"
[1] "in baz - before <<-"
[1] "in baz - after <<-"
> bar
[1] "global"

Pertama kali kami mencetak bilah yang belum kami panggil, foomaka itu harus tetap bersifat global - ini masuk akal. Kedua kalinya kami mencetaknya foosebelum menelepon bazsehingga nilai "in foo" masuk akal. Berikut ini adalah di mana kita melihat apa <<-yang sebenarnya dilakukan. Nilai berikutnya yang dicetak adalah "dalam baz - sebelum << -" meskipun pernyataan cetak muncul setelah <<-. Ini karena <<-tidak terlihat di lingkungan saat ini (kecuali jika Anda berada di lingkungan global di mana kasing <<-bertindak <-). Jadi di bazdalam nilai bar tetap sebagai "in baz - before << -". Setelah kita memanggil bazsalinan bilah di dalam foodiubah menjadi "dalam baz" tetapi seperti yang kita lihat global bartidak berubah.baryang didefinisikan di dalam fooberada di lingkungan induk ketika kami membuat bazjadi ini adalah salinan pertama dari baryang <<-melihat dan dengan demikian salinan yang ditugaskan kepadanya. Jadi <<-bukan hanya secara langsung menugaskan ke lingkungan global.

<<-itu rumit dan saya tidak akan merekomendasikan menggunakannya jika Anda dapat menghindarinya. Jika Anda benar-benar ingin menetapkan ke lingkungan global, Anda dapat menggunakan fungsi tetapkan dan katakan secara eksplisit bahwa Anda ingin menetapkan secara global.

Sekarang saya mengubah <<-ke pernyataan penetapan dan kita dapat melihat apa efeknya:

bar <- "global"
foo <- function(){
    bar <- "in foo"   
    baz <- function(){
        assign("bar", "in baz", envir = .GlobalEnv)
    }
    print(bar)
    baz()
    print(bar)
}
bar
#[1] "global"
foo()
#[1] "in foo"
#[1] "in foo"
bar
#[1] "in baz"

Jadi kedua kali kita mencetak bilah di foodalam nilainya "di foo" bahkan setelah menelepon baz. Ini karena assignbahkan tidak pernah mempertimbangkan salinan bagian bardalam foo karena kami mengatakannya ke mana harus mencari. Namun, kali ini nilai bar di lingkungan global berubah karena kami secara eksplisit ditugaskan di sana.

Sekarang Anda juga bertanya tentang membuat variabel lokal dan Anda dapat melakukannya dengan cukup mudah tanpa membuat fungsi ... Kita hanya perlu menggunakan localfungsi.

bar <- "global"
# local will create a new environment for us to play in
local({
    bar <- "local"
    print(bar)
})
#[1] "local"
bar
#[1] "global"
Alasan
sumber
2

Sedikit lagi di jalur yang sama

attrs <- {}

attrs.a <- 1

f <- function(d) {
    attrs.a <- d
}

f(20)
print(attrs.a)

akan mencetak "1"

attrs <- {}

attrs.a <- 1

f <- function(d) {
   attrs.a <<- d
}

f(20)
print(attrs.a)

Akan mencetak "20"

SemanticBeeng
sumber