標籤:

r語言中句號(點號)「.」的含義是什麼?

如題,初學R,對R整體的編程範式不是很理解,感覺很雜,有面向對象也有函數式也有其他的各種各樣的東西。然後這個句號的問題一直困擾我。一般「.」都是用來引用對象中的屬性之類的,但是R裡面的「.「是做什麼用的呢?比如read.csv()又比如is.na()。還是說他沒有特殊含義?


R中的 . 符號只是個普通字元,可以在符號名稱中出現,下面幾種情況中 . 具有特殊含義:

1. 一個 environment 中以 . 開頭的變數默認被當作隱藏變數,用 ls.str() 不會被列出來,除非 ls.str(all.names = TRUE) .

2. 一些函數中 . 具有特殊的意義,比如線性模型函數 lm() 的 formula 參數中的 . 符號會被特殊解讀,比如 lm(mpg ~ ., data = mtcars) 中 mpg ~ . 這個formula會被lm()解讀成在mtcars數據表中以mpg為被解釋變數,其他列為解釋變數做線性回歸模型,在變數很多的情況下可以簡化代碼,但風險是數據列變化時回歸方程也跟著變,有些類似於SQL中使用 select * 的風險。

3. 不同的函數可能讓 . 擁有不同的含義,比如dplyr::do()函數中的 . 就是指每個數據行,而magrittr::`%&>%`右側函數參數中出現的 . 是指符號左邊的對象,pipeR::`%&>&>%`右側表達式中的 . 是指符號左邊的對象,rlist::list.map() 函數 expr 參數中的 . 被解讀成 implicit lambda expression,表示需要映射的list中的每個元素本身。

4. (感謝 @王雨晨 的回答,差點遺忘了對於R來說最關鍵的一點).符號被專門用來實現R中一個比較簡單的面向對象系統S3的method dispatch,即可以用UseMethod()定義一個方法xyz,那麼xyz.class這指xyz方法對於class類型的實現。這種S3面向對象系統比較簡單,也容易發生混淆,比如head.data.frame實際上是head對於data.frame類型的實現,但也可以定義head.data方法,然後定義一種frame類型,這樣在代碼中就會發生混淆。

總而言之,. 符號在一般的變數中只是一個普通符號而已,只不過有些函數用 . 提供特殊用法方便書寫或引用,或者用作S3系統中分隔方法與類的字元。

=== 補充 1 ===

R中訪問對象中的元素有多種情況,一類是取子集(subsetting),用 [] ,比如一個 list(a=1,b=2) ["a"] 獲得 list(a=1),該運算對list, vector等對象有定義,對environment沒有定義;還有一類是取元素(extracting),用 [[ ]] ,list(a=1, b=2) [["a"]] 獲得元素值 1,這種情況也可以用 $ 來取元素,該計算對於environment有定義,但$對vector無定義。另外還有S4對象,需要用@ 符號來訪問slot,背後對應的函數是slot()函數,不過這些也不是定死的,對於自己定義的對象總可以去自己實現 "[", "[[", "$" 等方法來定義如何計算,可以參見我的 renkun-ken/pipeR @ GitHub 擴展包中Pipe對象的 $.Pipe() (pipeR/pipe.R at master · renkun-ken/pipeR · GitHub),就可以動態生成 closure 實現彷彿 jQuery 或者 C# LINQ 一樣的以對象為基礎的管道操作。


我認為最關鍵的作用應該是服務於S3的面向對象編程。

雖然R中沒有完全遵照S3這個面向對象的系統,但是大部分統計功能是用S3實現的。默認在泛型函數後面用「.」加上類型名來表示針對某一類對象的函數。如泛型函數summary,其下有32種針對不同類型的「方法」,可以用

methods(summary)

來查看。如果你用lm擬合了一個線性模型,線性模型是一種特殊類型的統計對象,不同的函數在對擬合的模型做分析時需要用針對線性模型的方法來處理。於是還可以用

methods(class = "lm")

來查看當前的對象被哪些具體的函數來支持(35個)。

泛型函數的一個好處是使代碼更可讀。比如你擬合了一個線性模型後,需要對其做方差分析,可以用

fit &<- lm(...) anova(fit)

這裡調用了泛型函數anova,但實際上它會調用anova.lm。當你之前的fit換用了其他模型時,比如glm,第二句是不用變的,還是只需要調用anova,R就會自動找到anova.glm來處理。

所以「.」並不只是命名習慣而已,在R語言中對它定義了特殊的語法。


@任坤 說的很全面了。額外補充一點就是,如果說「一般「.」都是用來引用對象中的屬性之類的」,似乎R中"$"更符合這一的描述,而「.「真的就是個普通字元而已~


推薦閱讀:

R語言分層抽樣的函數是什麼?
R中的列表(list)和數據框(data.frame)有什麼區別?
用R可以做數據清洗嗎?或者有更好的數據清洗工具?
R語言里做時間序列分析有哪些包?
Microsoft R open和Microsoft R server和普通的R語言有什麼區別和聯繫?

TAG:R編程語言 |