使用 purrr 進行函數語言程式設計


函數語言程式設計是一種程式設計方法,我們透過構造和應用函式來構建程式。更具體地說,在程式中,我們應用順序的純函式而不是語句。純函式是指接受輸入併產生一致輸出值的函式。此外,在此過程中不會修改任何增強或輸入流。此類函式能夠執行單個操作,但為了執行復雜的操作,我們可以將它們組合成序列。

在本教程中,我們將討論使用 purrr 進行函數語言程式設計。如今,函數語言程式設計由於其解決複雜問題的能力而變得很重要。

R 中的函數語言程式設計

我們可以使用 purrr 包在 R 中實現函數語言程式設計。您可以使用以下 CRAN 命令安裝 purrr 包:

install.packages("purrr")

如您所見,我們已成功在系統中安裝了 purrr 包。

Map_() 系列函式

purrr 包為我們提供了 map_() 系列函式,使用這些函式我們可以實現函數語言程式設計以獲得與 for 和 while 迴圈相同的輸出。

map_() 函式有多種形式。讓我們一一來看:

map() 函式

語法

這是最基本的函式。它接受一個向量和一個函式作為引數,然後為向量中的每個元素呼叫該函式。該函式的語法如下所示:

map(vector, function)

它接受一個向量和一個函式作為引數。它返回一個列表作為輸出。

示例

考慮以下給出的程式:

# Import library
library("purrr")

# Create a vector
myVector <- c(8, 3, 7, 2, 11, 20)

# Define a function
subtractByThree <- function(x) x - 3

# Print the output list 
print(map(myVector, subtractByThree))

輸出

[[1]]
[1] 5

[[2]]
[1] 0

[[3]]
[1] 4

[[4]]
[1] -1

[[5]]
[1] 8

[[6]]
[1] 17

如上所示,在從給定向量的所有元素中減去 3 後,會生成一個列表。

示例

現在讓我們嘗試再次執行與上面相同的操作,但這次使用迴圈。如您在原始碼中看到的,這次在迴圈的情況下,它需要我們編寫更復雜的程式碼。

# Create a vector
myVector <- c(8, 3, 7, 2, 11, 20)

# Create a list of size six
subtractByThree <- vector("list", 6)

# Iterate using a for loop
# and calculate the result
# for each value in the vector
for(currentNumber in seq_along(myVector)){
   subtractByThree[[currentNumber]] <- myVector[currentNumber] - 3
}

# Print the list
print(subtractByThree)

輸出

[[1]]
[1] 5

[[2]]
[1] 0

[[3]]
[1] 4

[[4]]
[1] -1

[[5]]
[1] 8

[[6]]
[1] 17

如上所示,在從給定向量的所有元素中減去 3 後,會生成一個列表。

因此,我們可以說在程式碼中使用 map() 可以減少程式碼量(與迴圈相比),並且我們也不需要建立空列表來儲存結果。

map() 函式還為我們提供了更簡單的方法來根據位置和名稱從向量中提取元素。例如:

示例

在下面的程式中,我們建立了一個列表的列表,並且我們首先使用位置然後使用標題名稱訪問元素。

# Import the library
library("purrr")

# Create a list of lists
myList <- list(list(data1 = 0.1, data2 = 1, data3 = "p"), list(data1 = 0.2, data2 = 4, data3 = "q"), list(data1 = 0.3, data2 = 8, data3 = "r")
)

# Access using position
map(myList, 2)

輸出

[[1]]
[1] 1

[[2]]
[1] 4

[[3]]
[1] 8

使用標題名稱訪問

map(myList, "data3")

輸出

[[1]]
[1] "p"

[[2]]
[1] "q"

[[3]]
[1] "r"

如上所示,首先列印第二位置的元素(使用位置),然後列印第三位置(使用標題名稱)的元素。

map_chr() 函式

語法

顧名思義,map_char() 函式返回字串的原子向量。此函式具有以下語法:

map_chr(vector, function)

它接受一個向量和一個函式作為引數。它返回一個字串的原子向量。

示例

讓我們考慮一個說明此函式工作原理的程式:

# Import library
library("purrr")

# Create a vector
myVector <- c(8, 3, 7, 2, 11, 20)

# Define a function
subtractByThree <- function(x) x - 3

# Print the output list 
print(map_chr(myVector, subtractByThree))

輸出

[1] "5.000000"  "0.000000"  "4.000000"  "-1.000000" "8.000000"  "17.000000"

如輸出所示,操作的結果作為字串向量返回。

map_dbl() 函式

語法

顧名思義,map_dbl() 函式返回雙精度型別的原子向量。此函式具有以下語法:

map_dbl(vector, function)

它接受一個向量和一個函式作為引數。它返回一個雙精度型別的原子向量。

示例

讓我們考慮一個說明此函式工作原理的程式:

# Import library
library("purrr")

# Create a vector
myVector <- c(8, 3, 7, 2, 11, 20)

# Define a function
subtractByThree <- function(x) x - 3

# Print the output list 
print(map_dbl(myVector, subtractByThree))

輸出

[1]  5  0  4 -1  8 17

如輸出所示,操作的結果作為雙精度資料型別的向量返回。

reduce() 函式

語法

函數語言程式設計的另一個動機是減少。purrr 包為我們提供了 reduce() 函式,使用該函式我們可以將列表中的值的數量減少到單個值。此函式具有以下語法:

reduce(list, operation)

它接受一個列表和要對列表的值執行的操作。它返回一個單一的值。

示例

讓我們考慮以下演示 reduce() 函式工作原理的程式:

# Import library
library("purrr")

# Apply reduce() function
reduce(seq(1:10), `*`)

輸出

[1] 3628800

如上所示,我們對列表的所有元素應用了乘法運算,並生成了一個單一的值作為輸出。

故障排除錯誤

在開發領域,故障排除特定程式或軟體中的問題的能力非常重要。如果程式中涉及列表,那麼它變得更加重要,因為在字串的情況下查詢問題會變得很棘手。

安全地遍歷 Map over safely() 函式

當我們遍歷列表時,有時某些操作的結果不會按照正確的資料型別出現。更具體地說,操作會導致無效值。在這種情況下,我們可以使用 safely() 函式來安全地使用 purrr。

在下面的程式中,我們正在計算列表所有元素的對數值。但是對於 -1,無法計算對數。因此,它可能會引發一些錯誤。但是我們在這裡使用 safely() 函式進行對映以獲取這些操作期間的結果和錯誤。由於我們希望在出現任何錯誤之前傳遞結果,因此我們應用了 transpose() 函式。

示例

# Import library
library("purrr")


# Map using safely
myList <- list(12, 11, 10, -1) %>% 
   map(safely(log, otherwise = NA_real_)) %>%
   # Transpose the outcome
   transpose()

# Print the result
print(myList)

# Print the result component
print(myList[["Result"]])

# Print the error component
print(myList[["Error"]])

輸出

$result
$result[[1]]
[1] 2.484907

$result[[2]]
[1] 2.397895

$result[[3]]
[1] 2.302585

$result[[4]]
[1] NaN


$error
$error[[1]]
NULL

$error[[2]]
NULL

$error[[3]]
NULL

$error[[4]]
NULL

列印結果元件

print(myList[["Result"]])

輸出

NULL

列印錯誤元件

print(myList[["Error"]])

輸出

NULL

如輸出所示,已顯示給定列表的各個元素的對數值。由於無法計算列表中 -1 的對數,因此相應的輸出值已替換為 NAN 值。您還可以分別在輸出中看到結果元件和錯誤元件。

安全地遍歷 Map over possibly() 函式

possibly() 函式執行與 safely() 函式幾乎相同的任務。唯一的區別是 possibly() 不會列印任何錯誤訊息。

示例

讓我們考慮以下程式:

# Import library
library("purrr")

# Map over possibly()
myList <- list(12, 11, 10, -1) %>% 
map(possibly(function(data){
   log(data)
},NA_real_))

# Print the list
print(myList)

輸出

[[1]]
[1] 2.484907

[[2]]
[1] 2.397895

[[3]]
[1] 2.302585

[[4]]
[1] NaN

如輸出所示,已顯示給定列表的各個元素的對數值。由於無法計算列表中 -1 的對數,因此相應的輸出值已替換為 NAN。

結論

在本教程中,我們討論了使用 purrr 包進行函數語言程式設計。我們從什麼是 R 中的 purrr 包以及如何使用 CRAN 安裝它開始,然後我們看到了 map 函式的不同版本及其工作原理。最後,我們討論了使用 safely() 和 possibly() 函式進行故障排除的方法。我希望本教程將幫助您提高資料科學領域的相關知識。

更新於: 2023年1月17日

252 次瀏覽

開啟您的 職業生涯

透過完成課程獲得認證

開始
廣告

© . All rights reserved.