HOWTO · R

R 中的 replicate()函式

本教程介紹了 R 中 replicate()函式的使用。

本頁內容

R 的 replicate() 會重複評估運算式,並收集每次評估的結果。當相同計算、隨機抽樣或模擬需要執行多次時,這個函式就很實用。結果的形狀取決於運算式傳回的內容,以及 simplify 引數的設定;收集的值可能會組成向量、矩陣、陣列或清單。

replicate() 會重複執行什麼

第一個引數 n 指定評估次數;第二個引數 expr 則會在每次重複時評估一次。例如,以下範例會傳回五個純量值 1:

執行此範例:

本節中的程式碼以及顯示的標籤或輸出仍為英文。

result <- replicate(5, 1)
print(result)

傳回的向量中,每次評估各有一個值。如果 expr 使用隨機性,每次評估都可能得到不同的值;replicate() 只會收集這些結果,不會讓它們變得相同。

語法與 simplify 引數

一般形式為 replicate(n, expr, simplify = "array")。其中,n 是重複次數,expr 是要評估的運算式,而 simplify 則控制 R 如何簡化收集到的結果。預設值 "array" 會依結果的形狀進行簡化:純量結果可以組成向量,長度相同的向量可以組成矩陣,而更高維度的結果則可以組成陣列。若要保留清單,可使用 simplify = FALSE;例如,每次重複所傳回的結果都應保留為獨立物件時,就適合這樣做。

執行此範例:

本節中的程式碼以及顯示的標籤或輸出仍為英文。

values <- replicate(3, c("red", "blue"), simplify = FALSE)
print(typeof(values))
print(length(values))
[1] "list"
[1] 3

typeof() 會回報底層型別,而 length() 會計算清單中的元素數量。

重複純量或向量

純量運算式會在每次重複時產生一個結果。如果運算式每次都傳回長度相同的向量,replicate() 會將各向量放在矩陣的一欄。如此一來,矩陣的列對應向量中的位置,欄則對應重複次數。

執行此範例:

本節中的程式碼以及顯示的標籤或輸出仍為英文。

result <- replicate(3, seq(1, 4))
print(result)

若計算會傳回固定長度的向量,也可以使用相同模式。如果結果長度不固定,這些值就無法排列成規則的矩陣;此時可設定 simplify = FALSE,讓每個結果保留在清單的個別元素中。

使用 replicate() 搭配 for() 迴圈

for() 迴圈可以建立一個值,作為每次重複的結果。在運算式中初始化並填入向量,接著讓該向量成為運算式最後評估的值:

執行此範例:

本節中的程式碼以及顯示的標籤或輸出仍為英文。

result <- replicate(2, {
  values <- numeric(4)
  for (i in seq_len(4)) {
    values[i] <- i * 2
  }
  values
})
print(result)

最後評估的運算式是 values,因此每次評估都會傳回填好的向量;簡化後的結果則是每次重複各占一欄。for() 迴圈本身會傳回 NULL;在迴圈中列印值,不會讓那些列印出的值變成迴圈的傳回值。如果重複執行的運算式只有這種迴圈,每次重複都會傳回 NULL。若要在結果中取得這些值,請先儲存它們,再傳回存放這些值的物件。

重複執行隨機模擬

隨機運算式會在每次重複時重新評估。例如,rnorm(4) 會從標準常態分布抽取四個值。產生的矩陣每欄包含一次抽取的四個值;抽樣結果會隨執行次數而變,因此不應將其視為固定輸出。

執行此範例:

本節中的程式碼以及顯示的標籤或輸出仍為英文。

set.seed(42)
draws <- replicate(3, rnorm(4))
print(dim(draws))

也可以重複執行模擬函式。定義函式,使其傳回感興趣的統計量或測量值,再將該函式的呼叫作為 expr 傳入。例如,若函式使用 runif(1) 抽取一個值,就能多次評估該函式,以研究模擬值的分布。若需要可重現的隨機序列,請選擇並記錄種子;若未固定種子,各次執行的值通常會不同。

使用 replicate() 進行 bootstrap 重抽樣

Bootstrap 重抽樣會從觀測資料中以放回方式抽取樣本,以估計不確定性。每次重複時,sample() 都會建立一份重抽樣資料集。如果每份樣本的大小都與原始資料相同,簡化後的輸出會是矩陣,且每一欄代表一次 bootstrap 重複。

執行此範例:

本節中的程式碼以及顯示的標籤或輸出仍為英文。

original_data <- c(2, 4, 6, 8, 10)
set.seed(42)
resamples <- replicate(5, sample(original_data, replace = TRUE))
print(dim(resamples))

每一欄代表一份重抽樣資料集;由於抽樣採放回方式,同一個值可能出現不只一次。如果想對統計量進行 bootstrap,而不是保留每個抽樣值,可以在重複執行的運算式中計算統計量,例如 mean(sample(original_data, replace = TRUE))。這樣每次重複會產生一個統計量,通常會收集成向量。