20151019 [Coursera] R Programming (8)

整理自 R Programming (Week 2) -- Function

[ Week 2 課程內容 ]
 
 
[ 筆記內容 ] 
  • (一)Functions (part 1)
  • [ 重點整理 ] 關於函數 - functions
  • 1.  基本概念
  • 2.  參數
  • 3.  使用方式
  • (二)Functions (part 2)
  • [ 重點整理 ] 函數的定義與使用
  • 1.  自訂函數
  • 2.  惰性求值 - Lazy Evaluation
  • 3.  特殊參數 - "..." 
 
 
 
 

(一)Functions (part 1)

[ 參考資料 ]
 
 
[ 重點整理 ] 關於函數 - functions
1.  基本概念
  • 建立時直接使用 "function()",在 R 的類別裡屬於 "function",範圍以 {...} 表示。
  • 在 R 裡面屬於 "第一級物件(first class objects)",使用上就跟其他物件類型一樣(可以賦予值、傳遞參數、回傳結果)。
  1. 可以傳遞參數給其他函數
  1. 可以在函數裡定義其他函數
  1. 會回傳函數內最後一個表達式的結果
# function() 的使用
f <- function(arguments) {    # arguments  參數 (在這裡是"形式"參數)
    ## Do something interesting
}
 
 
2.  參數
  • 形式參數是在函數定義時被包含進去的參數
  • 使用 args() 會把 "()" 內輸入的函數名當作參數,並回傳該函數所有形式參數。
  • 在 R 裡面不是每一次函數呼叫都會使用到所有的形式參數,也就是說形式參數可以空白(當使用者沒有賦予參數內容時,其值為 "預設值")。
  • [ 範例 ] 形式參數
function(arguments) {    # "形式參數"
    ...
}
 
 
3.  使用方式
  • 函數的參數會根據名稱或是位置來匹配。
  • 當使用者給參數進行命名時,就不需要讓參數按照特定順序排列
  • [ 範例 ] 計算標準差的函數 "sd()" 為例,以下函數皆為相同的執行結果:
# 計算標準差函數"sd()",其預設的用法為 "sd(x, na.rm = FALSE)"
# 用"sd()"讀入一個名為"x"的向量、用"na.rm"來判斷是否移除向量裡的缺失值。
> mydata <- rnorm(100)    # 模擬100個正態分布的隨機數值,並將結果存入"mydata"
> sd(mydata)    # 沒有對參數進行命名,所以預設"mydata"為第一個參數並將其傳遞給函數
[1] 0.9992897
> sd(x = mydata)    # 對參數"x"進行命名,"x = mydata"
[1] 0.9992897
> sd(x = mydata, na.rm = FALSE)    # 對所有參數進行命名,令"x = mydata, na.rm = FALSE"
[1] 0.9992897
> sd(na.rm = FALSE, x = mydata)    # 對所有參數進行命名,令"x = mydata, na.rm = FALSE"
[1] 0.9992897
> sd(na.rm = FALSE, mydata)    # 對調參數的順序,令"na.rm = FALSE, x = mydata"
[1] 0.9992897
>                              # 儘管可以對調參數的位置,但是不建議這樣做,因為很容易搞混。
 
  • 混合使用位置匹配和命名 >> 適用於參數極多的函數
  • 匹配的優先順序
  • 函數參數可以進行部份匹配,當某個函數的參數名稱很長時,可以使用部份匹配來輸入部份參數名。其順序為 : 
  1. 完全匹配 >> 檢查參數名稱是否完全匹配
  1. 部份匹配 >> 檢查參數名稱是否部份匹配
  1. 位置匹配 >> 根據參數的位置進行匹配
 
  • [ 範例 ] "lm()" 將數據資料比對至線性模型
# 使用"args()"來顯示"lm()"所有可使用的參數
> args(lm)    # 顯示lm()所有可使用的參數
function (formula, data, subset, weights, na.action,
 method = "qr", model = TRUE, x = FALSE,
 y = FALSE, qr = TRUE, singular.ok = TRUE,
 contrasts = NULL, offset, ...)
  • 以下為沒有"預設值"的參數 << 使用者必須指定它們的值
  • formula    公式
  • data    數據
  • subset    子集
  • weights    權重
  • na.action    當數據內包含"NA"值時,該採取何種行動
 
 
 
 

(二)Functions (part 2)

[ 參考資料 ]
 
 
[ 重點整理 ] 函數的定義與使用
1.  自訂函數
  • 建立自訂函數時,需要 "給予參數名稱" 以及確定這些參數是否有 "預設值"
  • [ 範例 ] 自訂函數
  • 參數 "a" 沒有給予預設值
  • 參數 "b = 1"、"c = 2"
  • 參數 "d = NULL"
f <- function(a, b = 1, c = 2, d = NULL) {
}
 
 
2.  惰性求值 - Lazy Evaluation
  • 僅在函數參數被使用時對它進行求值 (被動)
  • [ 範例1 ] 惰性求值_(1)
> f <- function(a, b) {    # 在函數主體只用了一個參數,求"a"的平方,並回傳結果。
+     a^2
+ }
> f(2)
[1] 4
  • 本函數從未使用參數 "b" ,且 R 會根據參數位置進行位置匹配,所以在使用 "f(2)" 時只會對應到參數 "a" ,並不會出現錯誤。
 
[ 範例2 ] 惰性求值_(2)
> f <- function(a, b) {
+     print(a)
+     print(b)
+ }
> f(45)
[1] 45
Error in print(b) : argument "b" is missing, with no default
  • 執行結果會先列印出 "45" 再顯示錯誤訊息。因為 "print(b)" "print(a)" 之後才會被用到,即參數 "b" 在之後才會被觸發到;一旦 "print(b)" 被執行時,就會出現錯誤訊息。
 
 
3.  特殊參數 - "..." 
  1. "..."(點點點) 用來表示一些可以傳遞給其他函數的參數
  1. 常用於擴展另一個函數,但又不想複製原函數的整個參數列表
  •  [ 範例 ] 特殊參數 - "..."
# 傳遞"..."之前的參數,在此為"(x, y, type = "1")"
> myplot <- function(x, y, type = "1", ...) {
+     plot(x, y, type = type, ...)    # 傳遞"..."之前的參數,在此為"(x, y, type = type)"
+ }
 
  • "泛型函數(gernic functions)"
  • "..." 的另外一種用途,使得泛型函數的附加参数可以傳遞给方法 (method)
> mean
function (x, ...) 
UseMethod("mean")
<bytecode: 0x0848c528>
<environment: namespace:base>
 
  • 當傳遞給函數的參數數量無法確定時,也會使用 "..."
  • [ 範例 ] paste()、cat()
  • 因為該函數的參數數量無法確定,所以用 "..." 代替。
# paste() : 將一組字串連接起來,來新建一個新的字串或字元向量
# cat() : 將一些字串連接起來,然後將連接後的字串輸出到文件或者是命令列
>
> args(paste)
function (..., sep = " ", collapse = NULL)     # sep : 設定分隔符號,預設為"空格"
NULL
> args(cat)
function (..., file = "", sep = " ", fill = FALSE, labels = NULL, 
    append = FALSE) 
NULL
 
  • 任何出現在 "..." 後面的參數都要明確的指定參數名稱,而且不能使用 "位置匹配" "部份匹配"
  • [ 範例 ] 出現在 "..." 後面的參數
  • 在範例中,我們需要連接 "a" "b" ,其分隔符號為 " : " (冒號) ,表示希望在連接兩個對象之間要用 " : " 隔開。
> args(paste)
function (..., sep = " ", collapse = NULL) 
NULL
> # 在"..."後面出現的參數都要明確的指定參數名稱,如下所示:
> paste("a", "b", sep = ":")    # 分隔符號為":",表示在連接兩個對象之間要用":"隔開
[1] "a:b"
> # 在"..."後面如果沒有完整指定參數名稱,會讓 R 以為該參數的內容也是"..."參數的一部份,如下所示:
> paste("a", "b", se = ":")
[1] "a b :"