您遇到問題的原因是您將對象傳遞給函數的本地名稱空間。這是關於R的偉大/可怕的事情之一:它允許隱式變量聲明,然後在名稱空間變得更深時實現超越。
這會影響你,因爲函數在當前名稱空間內創建一個新的名稱空間。我假設對象'myTable'最初是在全局命名空間中創建的,但是當它傳遞到函數'title.asterisk'時,新的函數 - 本地命名空間現在具有一個具有相同屬性的對象。這是這樣工作的:
title.asterisk <- function(myTable){ do some stuff to 'myTable' }
在這種情況下,函數'title.asterisk'不會對全局對象'myTable'進行任何更改。而是使用相同的名稱創建本地對象,以便本地對象取代全局對象。如果我們以這種方式調用函數title.asterisk(myTable)
,則該函數僅對局部變量進行更改。
有兩種直接的方法來修改全局對象(以及許多間接方法)。
選項1:第一,你提到,是有函數返回的對象和覆蓋全球的對象,像這樣:
title.asterisk <- function(myTable){
do some stuff to 'myTable'
return(myTable)
}
myTable <- title.asterisk(myTable)
這是正常的,但你仍然讓你代碼有點難以理解,因爲實際上有兩個不同的'myTable'對象,一個是全局的,一個是本地的。很多編碼者通過添加一段時間來解決這個問題。在可變參數前面,像這樣:
title.asterisk <- function(.myTable){
do some stuff to '.myTable'
return(.myTable)
}
myTable <- title.asterisk(myTable)
好吧,現在我們有一個視覺提示,兩個變量是不同的。這很好,因爲當我們稍後嘗試調試我們的代碼時,我們不希望依賴像命名空間超類這樣的不可見事物。這隻會讓事情變得比他們要難。
選項2:您可以修改該函數中的對象。當你想對一個對象進行破壞性的編輯並且不希望內存膨脹時,這是更好的選擇。如果您正在進行破壞性編輯,則無需保存原始副本。另外,如果你的對象適當大,你不想在你不需要時拷貝它。要編輯全局命名空間對象,不要將它傳入或從函數內部聲明它。
title.asterisk <- function(){ do some stuff to 'myTable' }
現在我們從函數內進行直接編輯對象「爲myTable」。我們沒有傳遞對象的事實使得我們的函數查看更高級別的名稱空間來嘗試和解析變量名稱。瞧,它發現了一個'myTable'對象更高!函數中的代碼將對對象進行更改。
需要考慮的注意事項:我討厭調試。我的意思是我真的討厭調試。這意味着我在R中有幾件事:
- 我把幾乎所有東西都包裝在一個函數中。當我編寫代碼時,只要我得到一塊工作,我將其包裝在一個函數中,並將其放在一邊。我大量使用'。'前綴爲我的所有函數參數,並且對於它存在的名稱空間的任何本機名稱,不使用任何前綴。
- 我嘗試不從函數內部修改全局對象。我不喜歡這導致。如果一個對象需要修改,我從聲明它的函數中修改它。這通常意味着我有調用函數的函數層,但它使我的工作既模塊化又易於理解。
- 我評論了我的所有代碼,解釋每一行或每塊的意圖。這似乎有點不相關,但我發現這三樣東西一起爲我着想。一旦你開始在函數中包裝代碼,你會發現自己希望重用更多的舊代碼。這就是好評。對我來說,這是一個必要的部分。
什麼對象類型是myTable? – 2013-03-19 11:16:58
詳細說明:「table title」是myTable對象的一個屬性,如果有的話,你使用哪個函數來首先設置屬性? – 2013-03-19 11:23:52
嗯,我對通用答案更感興趣,儘管我目前正在修改的實際表格是來自descr軟件包的CrossTable。標籤在創建對象時設置,我在說「attr(tbl $ t,'dimnames')[[2]] [level.index] = paste0(level.val,marker)」以添加星號到其中之一。 – 2013-03-19 12:09:53