For 迴圈的最優構造
為了說明 good for loop 構造的效果,我們將以四種不同的方式計算每列的平均值:
- 使用優化不佳的 for 迴圈
- 使用優化的 for 迴圈
- 使用
*apply
系列功能 - 使用
colMeans
功能
這些選項中的每一個都將以程式碼顯示; 將顯示執行每個選項的計算時間的比較; 最後將討論差異。
環路優化不佳
column_mean_poor <- NULL
for (i in 1:length(mtcars)){
column_mean_poor[i] <- mean(mtcars[[i]])
}
針對迴圈進行了優化
column_mean_optimal <- vector("numeric", length(mtcars))
for (i in seq_along(mtcars)){
column_mean_optimal <- mean(mtcars[[i]])
}
vapply
功能
column_mean_vapply <- vapply(mtcars, mean, numeric(1))
colMeans
功能
column_mean_colMeans <- colMeans(mtcars)
效率比較
對這四種方法進行基準測試的結果如下所示(程式碼未顯示)
Unit: microseconds
expr min lq mean median uq max neval cld
poor 240.986 262.0820 287.1125 275.8160 307.2485 442.609 100 d
optimal 220.313 237.4455 258.8426 247.0735 280.9130 362.469 100 c
vapply 107.042 109.7320 124.4715 113.4130 132.6695 202.473 100 a
colMeans 155.183 161.6955 180.2067 175.0045 194.2605 259.958 100 b
請注意,優化的 for
迴圈消除了構造不良的 for 迴圈。構造不良的 for 迴圈不斷增加輸出物件的長度,並且在每次改變長度時,R 重新評估物件的類。
通過在開始迴圈之前宣告輸出物件的型別及其長度,優化的 for 迴圈消除了一些此開銷負擔。
然而,在這個例子中,vapply
函式的使用使計算效率提高了一倍,主要是因為我們告訴 R 結果必須是數字(如果任何一個結果不是數字,則會返回錯誤)。
使用 colMeans
功能比 vapply
功能慢。這種差異可歸因於在 colMeans
中執行的一些錯誤檢查,主要是由於 vapply
函式中未執行的 as.matrix
轉換(因為 mtcars
是 data.frame
)。