R語言函數式編程purrr的應用

S語言的設計者、R語言核心團隊成員Chambers(2016)在Extending R一書中提到R語言中的三大理念。

Everything that exists in R is an object. OBJECT

Everything that happens in R is a function call.FUNCTION

Interfaces to other software are part of R. INTERFACE

在數據分析中,R語言函數式編程用的比較多。為此,Wickham等人編寫一個高級函數編程語言包purrr。

purrr enhances Rs functional programming (FP) toolkit by providing a complete and consistent set of tools for working with functions and vectors.

purrr在0.2.2版本之後有新的變化,變得更輕,更底層,分解為purrr和新的purrrlyr包。

purrr no longer depends on dplyr, lazyeval, or Rcpp. This makes the dependency graph of the tidyverse simpler, and makes purrr more suitable as a dependency of lower-level packages. This means that data-frame based mappers (dmap(), dmap_at(), dmap_if(), invoke_rows(), slice_rows(), map_rows(), by_slice(), by_row(), and unslice()) have been moved to a new package, purrrlyr. This is a bit of an aggressive change but it needed to be done, and in this case I think its better to rip the band aid off quickly.

R語言在運行時候速度確實一般,因此很多小夥伴得到的忠告就是避免使用循環,而是採用apply系列函數。(其實,在必要的時候,使用循環還是很方便的。

  • apply系列函數簡單應用

應用場景,求均值。分別採用了apply(mtcars,2,mean)、lapply(mtcars,mean)和sapply(mtcars,mean)。

> apply(mtcars,2,mean)n mpg cyl disp hp drat wt qsec vs am n 20.090625 6.187500 230.721875 146.687500 3.596563 3.217250 17.848750 0.437500 0.406250 n gear carb n 3.687500 2.812500 n> lapply(mtcars,mean)n$mpgn[1] 20.09062n$cyln[1] 6.1875n$dispn[1] 230.7219n$hpn[1] 146.6875n$dratn[1] 3.596563n$wtn[1] 3.21725n$qsecn[1] 17.84875n$vsn[1] 0.4375n$amn[1] 0.40625n$gearn[1] 3.6875n$carbn[1] 2.8125nn> sapply(mtcars,mean)n mpg cyl disp hp drat wt qsec vs am n 20.090625 6.187500 230.721875 146.687500 3.596563 3.217250 17.848750 0.437500 0.406250 n gear carb n 3.687500 2.812500 n

其實,這個時候採用函數式編程中常見的map也可以實現,上述的分析需求。R語言中的map需要大寫Map(函數,數據)。

> Map(mean,mtcars)n$mpgn[1] 20.09062n$cyln[1] 6.1875n$dispn[1] 230.7219n$hpn[1] 146.6875n$dratn[1] 3.596563n$wtn[1] 3.21725n$qsecn[1] 17.84875n$vsn[1] 0.4375n$amn[1] 0.40625n$gearn[1] 3.6875n$carbn[1] 2.8125n

  • purrr包

purrr包提供了大量的類似map的函數。可以服務於減少循環處理嵌套數據多模型等應用需求。

library(purrr)nlibrary(listviewer)ndata("mtcars") n

  • map

下面來看,map在數據進行標準化處理中的應用。

上述數據是list,應用起來不夠方便。下面轉成dataframe樣式。

  • map2

如果需要處理多個數據參數,就需要應用map2。

下面是生成多個正太分布隨機數。

  • pmap

如果是更多的參數,那麼就需要pmap。

  • modify

有時候需要對數據集中的變數進行修改或者生成新變數等。此時就可以使用modify。

  • 處理list等嵌套數據

生成嵌套數據

查看嵌套數據

提取嵌套數據

這樣看起來是不是很繁瑣?那麼就轉成data.frame吧!

  • 其他

purrr包還有很多其他的功能,這裡只介紹一些常用的。

例如,同時生成多個不同分布函數的隨機數,此時會用到invoke_map()。

purrr提供了簡化匿名函數的寫法。不過,為了可讀性,前文在介紹時,沒有採用這種寫法。

# 匿名函數-----nmap_df(mtcars, ~ .x * 2)nmap_df(mtcars, function(x) x * 2)n

這兩種寫法均可以滿足需求。

purr還有一種應用場景就是多模型分析。這個放在下一個分享中。

————————

參考資料:

1.Chambers, John M. Extending R. CRC Press, 2016.

2.Lessons and Examples

3.purrr function reference

分析環境

R version 3.4.0 (2017-04-21)n# devtools::install_github("tidyverse/purrr")nPackage: purrrnTitle: Functional Programming ToolsnVersion: 0.2.2.9000n

推薦閱讀:

Erlang入門教程 - 8. 在終端上輸出
編程範式與系統設計
幻想中的Haskell - Compiling Combinator
函數式又是函數式
Python 為什麼不能序列化函數閉包?

TAG:R编程语言 | 函数式编程 | 数据分析 |