R 語言使用者自訂函數

最早接觸「函數」,可以追溯到國高中,y 與 x 的線性組合 y = f(x)。x 是 input(可以不只一個)、y 是 output,兩者之間用 f (function) 來作轉換與連結。在 R 裡,當我們想避免複製大量重複的程式碼(複製貼上程式碼超過 2 次)、讓其他使用者可以使用我們設計的函數,就可以用 f <- function(x){運算程式碼; return(y)} 進行自訂函數。

老師舉的例子,是創造包含 a, b, c, d 四個各自有 20 個標準常態分配亂數的變數,如果我們想把原本的尺度轉換到 0-1 之間,發現同樣的程式碼要寫四次:

df <- data.frame(
  a = rnorm(20), # Generate 20 standard normal random numbers
  b = rnorm(20),
  c = rnorm(20),
  d = rnorm(20)
)

df$a <- (df$a - min(df$a, na.rm = TRUE)) / 
  (max(df$a, na.rm = TRUE) - min(df$a, na.rm = TRUE))
df$b <- (df$b - min(df$b, na.rm = TRUE)) / 
  (max(df$b, na.rm = TRUE) - min(df$a, na.rm = TRUE))
df$c <- (df$c - min(df$c, na.rm = TRUE)) / 
  (max(df$c, na.rm = TRUE) - min(df$c, na.rm = TRUE))
df$d <- (df$d - min(df$d, na.rm = TRUE)) / 
  (max(df$d, na.rm = TRUE) - min(df$d, na.rm = TRUE))

但透過自訂函數,我們可以精簡地、用別人也很容易了解的方式,把重複操作的流程轉為必要程式碼,接下來只要帶入我們想要的變數即可:

RescaleByRange <- function(x){
  rng <- range(x, na.rm = TRUE)
  return((x - rng[1]) / (rng[2] - rng[1]))
}

我們可以比較兩者的結果是一樣的,但用自訂函數的方式,畫面變得簡潔多了!只是對新手如我,還是需要多做一點思考與複習,才能看懂、甚至是把邏輯轉換成程式碼,要寫出更有效率的函數還是要多練習。

> df$a <- (df$a - min(df$a, na.rm = TRUE)) / 
+   (max(df$a, na.rm = TRUE) - min(df$a, na.rm = TRUE))
> df$a
 
[1] 0.6955101 0.6445714 0.3351554 0.1847988 0.3182214 0.5090866 0.5880603
 
[8] 0.9517401 0.1268596 0.4721010 0.6326112 0.6527196 1.0000000 0.4555521
[15] 0.5718586 0.3148169 0.1647536 0.6934324 0.6536277 0.0000000
> RescaleByRange(df$a)
 [1] 0.6955101 0.6445714 0.3351554 0.1847988 0.3182214 0.5090866 0.5880603
 [8] 0.9517401 0.1268596 0.4721010 0.6326112 0.6527196 1.0000000 0.4555521
[15] 0.5718586 0.3148169 0.1647536 0.6934324 0.6536277 0.0000000

練習題:撰寫一個名為 SummarizeData 的函數,回傳輸入向量的平均值 (mean)、變異數 (variance)、最大值 (maximum)、最小值 (minumum)、與中位數 (median)。

SummarizeData <- function(x){
  # Computes the summary statistics of a vector.
  #
  # Args:
  #   x: the vector you want whose summary statistics is calculated.
  #
  # Returns:
  #   A data frame with the mean, variance, maximum, minumum, and median of x.
  summary.df <- data.frame(x_mean = mean(x, na.rm = TRUE),
                           x_var = var(x, na.rm = TRUE),
                           x_max = max(x, na.rm = TRUE),
                           x_min = min(x, na.rm = TRUE),
                           x_median = median(x, na.rm = TRUE))
  return(summary.df)
}

SummarizeData(rnorm(10))

附上手邊的幾個部落格和線上課程網址:

Leave a Reply

Your email address will not be published. Required fields are marked *