這裡我們將詳細介紹 R 函數與 R 環境空間的使用方式。

環境空間

在 R 中所有的變數都是儲存在特定的環境空間(environments)中,而環境空間本身其實也是一種變數,可以當成一般變數使用(例如指定新的值、或是當成參數傳遞至函數中),它的性質跟列表(list)比較相近,甚至可以直接將列表變數轉換為環境空間變數,反之亦可。

通常我們在使用 R 的時候,不太需要去理會環境空間的問題,當我們在 R 的命令列建立一個變數時,R 會自動將該變數儲存在全域環境空間(global environment,這個空間也稱為 user workspace)中,另外當我們呼叫一個函數時,R 也會自動建立一個隸屬於該函數的環境空間來儲存與該函數相關的變數,理解變數以及環境空間的運作,可以幫助程式設計師更清楚 R 變數命名空間規則,以及程式除錯時的呼叫堆疊問題(call stack)。

若要建立一個新的 R 環境空間,可以呼叫 new.env

my.new.env <- new.env()

環境空間的操作方式跟列表變數相同,我們可以使用雙中括號或是錢字號的方式來在此環境空間中建立新的變數:

my.new.env[["name"]] <- "G.T.Wang"
my.new.env$foo <- c(1, 3, 5)

用來指定變數值的 assign 函數也可以使用 envir 參數來指定變數的環境空間:

assign(
  "bar",
  c(TRUE, FALSE, NA),
  my.new.env
)

要取出特定環境空間中的變數,也是跟列表的操作類似:

my.new.env[["name"]]
[1] "G.T.Wang"
my.new.env$foo
[1] 1 3 5

除此之外,也可以使用 get 函數:

get("bar", my.new.env)
[1]  TRUE FALSE    NA

lsls.str 函數也有提供使用者指定環境空間的功能:

ls(envir = my.new.env)
[1] "bar"  "foo"  "name"
ls.str(envir = my.new.env)
bar :  logi [1:3] TRUE FALSE NA
foo :  num [1:3] 1 3 5
name :  chr "G.T.Wang"

若要檢查特定的變數是否存在,可以使用 exists 函數:

exists("foo", my.new.env)
[1] TRUE

環境空間與列表之間若要互相轉換,可以使用 as.listas.environment 函數來處理:

my.list <- as.list(my.new.env)
my.list
$name
[1] "G.T.Wang"

$foo
[1] 1 3 5

$bar
[1]  TRUE FALSE    NA
as.environment(my.list)
<environment: 0x7fe9f2dd6a38>

list2env 也可以將列表轉為環境空間:

list2env(my.list)
<environment: 0x7fe9f2dd6a38>

在 R 中所有的環境空間都有繼承的關係,也就是說除了最頂層的空環境空間(empty environment)之外,任何一個環境空間都會有一個母環境空間(parent environment),在預設的狀況下,existsget 函數除了檢查目前的環境空間之外,也會一併檢查所有的母環境空間,如果要讓它只檢查目前的環境空間,可以加入 inherits = FALSE 參數:

child.env <- new.env(parent = my.new.env)
exists("name", child.env)
[1] TRUE
exists("name", child.env, inherits = FALSE)
[1] FALSE

我們在 R 命令列中所建立的任何變數預設都會被儲存於 global 這個環境空間中,若要取得 global 環境空間可以使用 globalenv 這個函數:

globalenv()
<environment: R_GlobalEnv>

或是直接取用 .GlobalEnv 這個變數也可以:

.GlobalEnv
<environment: R_GlobalEnv>

另外一個比較特別的環境空間是 base,他是 R 中最基本的一個環境空間,我們可以使用 baseenv 來取得之:

baseenv()
<environment: base>

其中儲存了很多 R 的基礎函數與運算子:

head(ls(envir = baseenv()), 20)
 [1] "-"            "-.Date"       "-.POSIXt"    
 [4] ":"            "::"           ":::"         
 [7] "!"            "!.hexmode"    "!.octmode"   
[10] "!="           "("            "["           
[13] "[.AsIs"       "[.data.frame" "[.Date"      
[16] "[.difftime"   "[.Dlist"      "[.factor"    
[19] "[.hexmode"    "[.listof"

parent.env 這個函數可以用來取得指定環境空間的母環境空間:

parent.env(globalenv())
<environment: 0x7fa52d118720>
attr(,"name")
[1] "tools:RGUI"

在 R 中會遇到環境空間的狀況主要有兩種,一種是呼叫函數時,每個函數會有自己專屬的環境空間(也稱為 closure),而另外一種則是載入各種 R 套件時,套件內的函數都會放在套件自己的環境空間中,透過搜尋路徑的方式來讓使用者取得套件內的各種函數,這些狀況會在之後的教學中詳細說明。