20151001 [R基礎與應用] Ch08 : 建立R函數

整理自 R 軟體資料分析基礎與應用 -- Ch08 : 建立R函數

[ 本次筆記內容 ]
  • (一)Hello World
  • (二)函數的引數
  • [ 前置作業 ] 使用 sprintf()
  • (1) 字串、特殊字元
  • (2) 建立字串
  • (3) name 引數
  • 1.  預設引數值
  • 2.  附加引數
  • (三)值的回傳
  • (四)do.call
 
 

(一)Hello World

  • 在控制台建立一個會顯示" Hello, World! "的函數
> # "say.hello"是函數名稱(裡面的"."是普通字元,沒有特殊意義)
> # 函數"function()以"{...}"裡面的內容作為函數主體
> say.hello <- function()    
+ {
+    print("Hello, World!")
+ }
> say.hello    # 呼叫函數
function()
{
    print("Hello, World!")
}
 
 
 
 

(二)函數的引數

[ 前置作業 ] 使用 sprintf()
  • (1) 字串、特殊字元
> # 取代一個特殊輸入字元
> sprintf("Hello %s", "Danny")
[1] "Hello Danny"
> # 取代兩個特殊輸入字元
> sprintf("Hello %s, today is %s", "Danny", "Friday")
[1] "Hello Danny, today is Friday"
 
 
  • (2) 建立字串
> # 用sprintf建立字串,並以輸入的引數來決定顯示結果
> hello.person <- function(name)
+ {
+     print(sprintf("Hello %s", name))
+ }
> hello.person("Danny")
[1] "Hello Danny"
> hello.person("John")
[1] "Hello John"
> hello.person("Manami")
[1] "Hello Manami"
> hello.person("Mason")
[1] "Hello Mason"
> hello.person("Martial Art")
[1] "Hello Martial Art"
> hello.person("Parkour")
[1] "Hello Parkour"    
 
 
  • (3) name 引數
  • name 引數在 "sprintf()" 裡被當成變數使用( 在函數外面不存在 ),基本上與其他變數無異,也可以被用在其他函數裡當引數。
  • 呼叫多於一個引數的函數時,可以把值輸入到引數的相對位置,或是直接指定引數名稱。
> hello.person <- function(first, last)
+ {
+     print(sprintf("Hello %s %s", first, last))
+ }
> # 透過引數相對位置
> hello.person("Danny", "Mason")
[1] "Hello Danny Mason"
> # 透過引數名稱
> hello.person(first = "Danny", last = "Mason")
[1] "Hello Danny Mason"
> # 把引數反過來
> hello.person(last = "Mason", first = "Danny")
[1] "Hello Danny Mason"
> # 只指定到一個引數名稱
> hello.person("Danny", last = "Mason")
[1] "Hello Danny Mason"
> # 指定另一個引數名稱
> hello.person(first = "Danny", "Mason")
[1] "Hello Danny Mason"
> # 透過引數名稱指定第二個引數, 接著在沒輸入引數名稱下指定第一個引數 
> hello.person(last = "Mason", "Danny")
[1] "Hello Danny Mason"
 
 
1.  預設引數值
  • 適用情況 : 當需要同時輸入多個以上的引數時,可使用預設引數值來增加效率。
  • 預設的值可以是"NULL"、"字元"、"數字"、" R 的任何有效物件"。
>
> hello.person <- function(first, last = "Doe")    # 以"Doe"作為預設的姓氏(last name)
+ {
+     print(sprintf("Hello %s %s", first, last))
+ }
> # 呼叫函數時不指定姓氏
> hello.person("Jared")
[1] "Hello Jared Doe"
> # 呼叫函數時指定其它的姓氏
> hello.person("Jared", "Lander")
[1] "Hello Jared Lander"
 
 
2.  附加引數
  • 允許使用者輸入任意數量的引數到函數裡(不用事先定義),透過"dot-dot-dot (...) 的引數"來完成。
>
> # 呼叫 hello.person, 並加入額外的引數
> hello.person("Jared", extra = "Goodbye")
Error in hello.person("Jared", extra = "Goodbye") : 
  unused argument (extra = "Goodbye")
> # 以兩個有效引數呼叫函數, 第三個引數是額外的
> hello.person("Jared", "Lander", "Goodbye")
Error in hello.person("Jared", "Lander", "Goodbye") : 
  unused argument ("Goodbye")
> # 現在建立 hello.person, 並加入 "..." 引數以接受附加引數
> hello.person <- function(first, last = "Doe", ... )
+ {
+     print(sprintf("Hello %s %s", first, last))
+ }
> # 呼叫 hello.person, 並加入額外的引數
> hello.person("Jared", extra = "Goodbye")
[1] "Hello Jared Doe"
> # 以兩個有效引數呼叫函數, 第三個引數是額外的
> hello.person("Jared", "Lander", "Goodbye")
[1] "Hello Jared Lander"
  •  
 
 
 

(三)值的回傳

  • 函數回傳執行結果的方式 : 
  1. 函數計算結束後的值自動被回傳。
  1. 使用 return 指令 (建議使用) >> 明確地指定所要回傳的值,同時作為該函數的結束
>
> # 建立函數時不使用 return 指令
> double.num <- function(x)
+ {
+     x * 2
+ }
> double.num(5)
[1] 10
> # 使用 return 指令建立
> double.num <- function(x)
+ {
+     return(x * 2)
+ }
> double.num(5)
[1] 10
> # 再次建立函數, 這次在 return 後面也放一些指令
> double.num <- function(x)
+ {
+     return(x * 2)   # 函數在這裡退出
+     
+     
+     #---以下指令不會被執行, 因為函數已經被退出了---
+     print("Hello !")
+     return(17)
+     #----------------------------------------------
+ }
> double.num(5)
[1] 10
 
 
 
 

(四)do.call

  • do.call 允許使用 character 或者物件來指定函數名稱其輸入的引數需以 列表(list) 呈現
>
> do.call("hello.person", args = list(first = "Jared", last = "Lander"))
[1] "Hello Jared Lander"
> do.call(hello.person, args = list(first = "Jared", last = "Lander"))
[1] "Hello Jared Lander"
> run.this <- function(x, func = mean)
+ {
+     do.call(func, args = list(x))
+ }
> # 用預設的 mean 函數找平均值
> run.this(1:10)
[1] 5.5
> # 指定要找平均值
> run.this(1:10, mean)
[1] 5.5
> # 計算總和
> run.this(1:10, sum)
[1] 55
> # 計算標準差
> run.this(1:10, sd)
[1] 3.02765