20151216 [Coursera] R Programming (11)

整理自 R Programming (Week 3) -- Loop Functions (1)

[ Week 3 課程內容 ]
 
 
[ 筆記內容 ] Loop Functions (1)
  • (一)Loop Functions - lapply
  • 1.  lapply()
  • [ 用法 ]
  • [ 範例1 ] "lapply()" 一定會回傳 "列表型態"的結果_(1)
  • [ 範例2 ] 利用"lapply()"處理多個以上元素所組成的列表
  • [ 範例3 ] "lapply()" 搭配 "runif()"_(1)
  • [ 範例4 ] "lapply()" 搭配 "runif()"_(2)
  • [ 範例5 ] "lapply()" 充分使用了 "匿名函數 (沒有函數名稱)"
  • 2.  sapply()
  • [ 用法 ]
  • [ 範例 ] "sapply()" 的使用方式
  • (二)Loop Functions - apply
  • 1.  apply()
  • [ 用法 ]
  • [ 範例1 ] 計算矩陣中每一列的平均值
  • [ 專用函數 ] 將"行(column)"和"列(row)"取 "總和" "平均值"
  • [ 範例2 ] 計算每一"行"的 25 和 75 百分位數
  • [ 範例3 ] 對陣列進行操作
 
 
 
 
[ 參考資料 ]
 
 
[重點整理] 
1.  lapply()
  • [ 用法 ]
lapply(X, FUN, ...)
  • "X":列表名稱 (如果"X"不是參數,將會用"as.list()"強制轉化為列表)
  • "FUN":被指定使用的函數
  • "...":傳遞參數 (對列表裡的每個元素做運算)
  •  
# 函數結構
> lapply
function (X, FUN, ...) 
{
    FUN <- match.fun(FUN)
    if (!is.vector(X) || is.object(X)) 
        X <- as.list(X)
    .Internal(lapply(X, FUN))
}
<bytecode: 0x003ece40>
<environment: namespace:base>
  •  
  • [ 範例1 ] "lapply()" 一定會回傳 "列表型態"的結果
# 建立由兩個元素組成的列表"x"
# "a": 一個"1~5"的數列向量、"b": 10個隨機組成的向量
> x <- list(a = 1:5, b = rnorm(10))
> lapply(x, mean)    # 利用"lapply()"對每個元素使用"mean(取均值)"函數
$a
[1] 3
 
$b
[1] -0.4332761
 
  • < 執行結果 >
 
  • [ 範例2 ] 利用"lapply()"處理多個以上元素所組成的列表
# 建立由四個元素組成的列表"x"
# "a": 一個"1~4"的數列向量
# "b": 10個隨機組成的向量
# "c"
> x <- list(a = 1:4, b = rnorm(10), c = rnorm(20, 1), d = rnorm(100, 5))
> lapply(x, mean)
$a
[1] 2.5
 
$b
[1] 0.4491021
 
$c
[1] 0.7762638
 
$d
[1] 4.970049
 
>
  • < 執行結果 >
 
  • [ 範例3 ] "lapply()" 搭配 "runif()"_(1)
> x <- 1:4    # 建立一個"1~4"的數列向量
> lapply(x, runif)
[[1]]                # runif(1) -- 產生 1 個均勻隨機數所組成的向量
[1] 0.5073698
 
[[2]]                # runif(2) -- 產生 2 個均勻隨機數所組成的向量
[1] 0.5588365 0.7042169
 
[[3]]                # runif(3) -- 產生 3 個均勻隨機數所組成的向量
[1] 0.5684885 0.9129467 0.1270256
 
[[4]]                # runif(4) -- 產生 4 個均勻隨機數所組成的向量
[1] 0.70262592 0.05725111 0.48480334
[4] 0.63522292
 
  • < 執行結果 >
 
  • [ 範例4 ] "lapply()" 搭配 "runif()"_(2)
  • 利用 "runif()" 產生介於 "0 - 10" 之間均勻的隨機數
> x <- 1:4
> lapply(x, runif, min = 0, max = 10)
[[1]]                # runif(1) -- 產生 1 個均勻隨機數所組成的向量
[1] 0.4063026
 
[[2]]                # runif(2) -- 產生 2 個均勻隨機數所組成的向量
[1] 1.021453 7.277391
 
[[3]]                # runif(3) -- 產生 3 個均勻隨機數所組成的向量
[1] 0.4952116 1.7786254 5.8042937
 
[[4]]                # runif(4) -- 產生 4 個均勻隨機數所組成的向量
[1] 3.628411 6.368390 2.289686 4.208043
 
  • < 執行結果 >
 
  • [ 範例5 ] "lapply()" 充分使用了 "匿名函數 (沒有函數名稱)"
  1. 先建立包含 2 個矩陣的列表。
  • 第一個為 2x2 的矩陣
  • 第二個為 3x2 的矩陣
  1. 接著再使用"匿名函數"提取這兩個矩陣的第一列,這個函數在 "lapply()" 之外不存在,當 "lapply()"執行完畢時此函數也會消失。
> x <- list(a = matrix(1:4, 2, 2), b = matrix(1:6, 3, 2))
> x
$a
     [,1] [,2]
[1,]    1    3
[2,]    2    4
 
$b
     [,1] [,2]
[1,]    1    4
[2,]    2    5
[3,]    3    6
 
> lapply(x, function(elt) elt[,1])    # 提取這兩個矩陣的第一列
$a
[1] 1 2
 
$b
[1] 1 2 3
 
  • < 執行結果 >
 
 
2.  sapply()
  • "lapply()" 的執行結果精簡化:
  • 若結果是每個"元素"長度皆為 "1" 的列表,將會回傳 "向量"。
  • 若結果是每個"向量"長度 (> 1) 皆相同的列表,將會回傳 "矩陣"。
  • 若無法精簡結果,則直接回傳列表。
  • [ 範例 ] "sapply()" 的使用方式
> x <- list(a = 1:4, b = rnorm(10), c = rnorm(20, 1), d = rnorm(100, 5))
> lapply(x, mean)
$a
[1] 2.5
 
$b
[1] -0.2601113
 
$c
[1] 0.9847573
 
$d
[1] 4.924048
 
> sapply(x, mean)
         a          b          c          d 
 2.5000000 -0.2601113  0.9847573  4.9240476 
> mean(x)
[1] NA
Warning message:
In mean.default(x) : argument is not numeric or logical: returning NA
  • < 執行˙結果 >
 
 
 
 

(二)Loop Functions - apply

[ 參考資料 ]
 
 
[重點整理] 
1.  apply()
  • 可以把一個函數 (可以是已經存在的函數或是"匿名函數") 應用在陣列的各個維度上面。
  • 經常用在處理矩陣的行或列
  • 可用於對一個矩陣取平均值
  • 需要輸入的參數較迴圈少,在命列列中相對好用。
  • [ 用法 ]
apply(X, MARGIN, FUN, ...)
  • "X":陣列 (有維度的向量)
  • "MARGIN":整數向量,用來指示哪一個維度(行或列)需要保留
  • "FUN":被指定使用的函數
  • "...":傳遞參數
 
# 函數結構
> str(apply)
function (X, MARGIN, FUN, ...)
 
  • [ 範例1 ] 計算矩陣中每一列的平均值
# 建立一個"20行10列的矩陣",矩陣裡是正態隨機產生的數字
> x <- matrix(rnorm(200), 20, 10)
>
> # 對所有"列"取平均值
> apply(x, 2, mean)    # 保留第2維度(列)、去掉第1維度(行)
 [1]  0.11502305  0.08063431 -0.19797862
 [4]  0.11195242 -0.02087351 -0.10817816
 [7]  0.03090089 -0.15335343 -0.05113633
[10] -0.12698686
> # 對所有"行"取總和
> apply(x, 1, sum)    # 保留第1維度(行)、去掉第2維度(列)
 [1]  1.1814590  0.4222659 -0.2816117
 [4] -6.9120684 -4.0285659 -1.6902687
 [7]  2.8261779  1.1060187  0.2605618
[10] -1.6894040 -1.7529009  1.7913958
[13]  0.6159366 -1.3019515 -3.4323064
[16] -1.3998466  2.1456304  1.6717134
[19] -0.4670733  4.5349132
  • < 執行結果 >
 
  • [ 專用函數 ] 將"行(column)"和"列(row)"取 "總和" "平均值"
  • 以下為計算矩陣"總和""平均值"的專用函數 (執行速度較"apply()"快速):
  • 列的計算 (row)
  • 取總和:rowSums() = apply(x, 1, sum)
  • 取平均值:rowMeans() = apply(x, 1, mean)
  • 行的計算 (column)
  • 取總和:colSums() = apply(x, 2, sum)
  • 取平均值:colMeans() = apply(x, 2, mean)
 
  • [ 範例2 ] 計算每一"行"的 25 和 75 百分位數
# 使用"quantile()"計算每一行的25和75百分位數
> x <- matrix(rnorm(200), 20, 10)    # 產生正態隨機分佈的數字
> apply(x, 1, quantile, probs = c(0.25, 0.75))
          [,1]       [,2]       [,3]
25% -0.2149464 -0.2594548 -0.3561782
75%  0.8696909  0.2799249  0.4112624
          [,4]       [,5]       [,6]
25% -0.6297229 -0.6243486 -0.5973480
75%  0.7634970  1.4804738  0.2396187
          [,7]        [,8]       [,9]
25% -0.6365716 -0.05352821 -0.8346142
75%  0.5377081  0.32721302  0.6480853
         [,10]     [,11]      [,12]
25% -0.2800897 0.2057999 -1.0142844
75%  0.6809832 0.7926215  0.9863733
         [,13]       [,14]      [,15]
25% -0.3001848 -0.81376360 -0.3670811
75%  0.9853322  0.03450025  0.9590299
         [,16]      [,17]       [,18]
25% -1.1587829 -0.6578810 -0.09577613
75%  0.4649419  0.8673224  0.27722560
         [,19]      [,20]
25% -0.7001218 -0.2333230
75%  0.4112067  0.1800692
  • < 執行結果 >
 
  • [ 範例3 ] 對陣列進行操作
# 建立一個"2行兩2"、"第3維度為10"的陣列
> a <- array(rnorm(2*2*10), c(2, 2, 10))
> apply(a, c(1, 2), mean)    # 保留第1和第2個維度、消除第3個維度,並取得平均值
            [,1]       [,2]
[1,] -0.02447451 0.81527620
[2,] -0.55271819 0.03986751
> rowMeans(a, dims = 2)
            [,1]       [,2]
[1,] -0.02447451 0.81527620
[2,] -0.55271819 0.03986751
  • < 執行結果 >