R for data Science(十三)

編寫函數

Code style

一般function后面都會有一個花括號{},用于填函數體,但是如果if 語句后面的函數句太短的時候,可以省略花括號:
如下:
y <- 10
x <- if (y < 20) "Too low" else "Too high"
書的作者只推薦非常簡短的if語句。否則,還是要用完整的花括號來更容易閱讀
if (y < 20) {  x <- "Too low" } else {  x <- "Too high"}

Function arguments

函數的參數通常分為兩大類:一組提供要計算的數據,另一組提供控制計算細節的參數。(data,detail)
例如:
在log()中,數據是x,而detail是對數的底。
在mean()中,數據是x,而細節是從結束(修剪)和如何處理缺失值(na.rm)中裁剪多少數據。
在t.test()中,數據是x和y,測試的細節是alternative, mu, paired, var.equal, 和 conf.level。
在str_c()中,您可以向…提供任意數量的字符串。,連接的細節由sep和collapse控制。
通常,數據參數應該放在首位。細節參數應該在末尾,并且通常應該具有默認值。您指定一個默認值的方式與使用命名參數調用函數的方式相同
# Compute confidence interval around mean using normal approximation
mean_ci <- function(x, conf = 0.95) {  se <- sd(x) / sqrt(length(x))  
alpha <- 1 - conf  mean(x) + se * qnorm(c(alpha / 2, 1 - alpha / 2))}
x <- runif(100)
mean_ci(x)
#> [1] 0.498 0.610
mean_ci(x, conf = 0.99)
#> [1] 0.480 0.628
當您調用一個函數時,您通常會忽略數據參數的名稱,因為它們非常常用。如果重寫細節參數的默認值,應該使用參數全名:
# Goodmean(1:10, na.rm = TRUE)##下面的形式就不友好# Badmean(x = 1:10, , FALSE)mean(, TRUE, x = c(1:10, NA))

Checking values

當你開始寫更多的函數時,你最終會忘記你的函數是如何工作的。此時,使用無效的輸入調用函數很容易。為了避免這個問題,明確約束通常是有用的。例如,假設您編寫了一些計算加權匯總統計的函數。
wt_mean <- function(x, w)
 {  sum(x * w) / sum(w)}
wt_var <- function(x, w)
 {  mu <- wt_mean(x, w)  sum(w * (x - mu) ^ 2) / sum(w)}
wt_sd <- function(x, w)
 {  sqrt(wt_var(x, w))}
你會發現x和w長度不同,但是R里面不會報錯,因為R里面可以增加循環
wt_mean(1:6, 1:3)
#> [1] 7.67

It’s good practice to check important preconditions, and throw an error (with stop()), if they are not true:

wt_mean <- function(x, w) { 
 if (length(x) != length(w)) {    stop("`x` and `w` must be the same length", call. = FALSE)  
}
 sum(w * x) / sum(w)}
image
如果你也加了一個na.rm參數,你可能不會仔細檢查。
wt_mean <- function(x, w, na.rm = FALSE) {
  if (!is.logical(na.rm))
 {    stop("`na.rm` must be logical")  }  
if (length(na.rm) != 1) {    stop("`na.rm` must be length 1")  }
  if (length(x) != length(w))
 {    stop("`x` and `w` must be the same length", call. = FALSE)  }  
if (na.rm) {    miss <- is.na(x) | is.na(w)    x <- x[!miss]    w <- w[!miss] 
 }
  sum(w * x) / sum(w)}
這是很多額外的工作,幾乎沒有額外的收獲。一個有用的折衷方案是內置的stopifnot():它檢查每個參數是否為真,如果沒有,則生成一個通用的錯誤消息.
wt_mean <- function(x, w, na.rm = FALSE) 
{ 
 stopifnot(is.logical(na.rm), length(na.rm) == 1) 
 stopifnot(length(x) == length(w))  
if (na.rm) {  
  miss <- is.na(x) | is.na(w)    x <- x[!miss]    w <- w[!miss] 
 } 
 sum(w * x) / sum(w)}
wt_mean(1:6, 6:1, na.rm = "foo")
#> Error in wt_mean(1:6, 6:1, na.rm = "foo"): is.logical(na.rm) is not TRUE
image

Return values

函數返回的值通常是它計算的最后一個語句,但是您可以使用return()選擇返回之前的值。作者認為最好保存return()的使用,以表明您可以使用更簡單的解決方案提前返回。
complicated_function <- function(x, y, z) {  
if (length(x) == 0 || length(y) == 0)
 {    return(0)  } 
 # Complicated code here}
當你有一個if語句,包含一個復雜塊和一個簡單塊。例如,您可以編寫這樣的if語句
f <- function() { 
 if (x) {
    # Do     # something    # that    # takes    # many    # lines    # to    # express  }
 else {    # return something short  
}}
但是如果第一個代碼塊很長,當你寫到else,你已經忘記了條件。那么你可以以一種簡單的方式重寫:
f <- function() {
  if (!x) {  
  return(something_short) 
 }  # Do   # something  # that  # takes  # many  # lines  # to  # express}

?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容

  • Lua 5.1 參考手冊 by Roberto Ierusalimschy, Luiz Henrique de F...
    蘇黎九歌閱讀 13,905評論 0 38
  • 第2章 基本語法 2.1 概述 基本句法和變量 語句 JavaScript程序的執行單位為行(line),也就是一...
    悟名先生閱讀 4,196評論 0 13
  • 今天分享一篇朋友寫的文章,字里行間透露著對人生的感悟,和智慧,灑脫。 我們每天的努力,不是為了去換取成功,也不是為...
    楠楠說閱讀 486評論 1 3
  • 【我讀】德魯克:優秀公司的五大標準:1.有效產出是衡量一家公司的最基本的底線標準;2.管理者的時間在哪里,公司的戰...
    四十剛好閱讀 185評論 0 0
  • NSMutableAttributedString *str = [[NSMutableAttributedStr...
    MMOTE閱讀 718評論 0 0