R语言mgarch包的说明_【R语言】优雅的循环迭代:purrr包

用 R 写 循环 从低到高有三种境界:手动 for 循环,apply 函数族,purrr 包泛函式编程。

补充一点, 关于purrr 与 apply 族:purrr 提供了更多的一致性、规范性和便利性,更容易记住和使用。速度来说,apply 族稍微快可以忽略不计的一丢丢。

本篇来谈一谈用 purrr 包优雅地做循环迭代。

先总述一下 purrr 包做泛函式循环迭代的核心思想,以及将要介绍的常用操作:

循环迭代,就是将一个函数依次应用(映射)到序列的每一个元素上。
  • map():依次应用一元函数到一个序列的每个元素上,基本等同 lapply()
  • map2():依次应用二元函数到两个序列的每对元素上
  • pmap():应用多元函数到多个序列的每组元素上,可以实现对数据框逐行迭代
  • map 系列默认返回列表型,可根据想要的返回类型添加后缀:_int, _dbl, _lgl, _chr, _df, 甚至可以接着对返回的数据框df做行/列合并:_dfr, _dfc
  • 如果只想要函数依次作用的过程,而不需要返回结果,改用 walk 系列即可
  • 所应用的函数,有 purrr公式风格简写(匿名函数),支持一元,二元,多元函数
  • purrr 包中的其它有用函数

下面结合实例具体展开。

先加载包:

library(tidyverse)

一. 预备知识

  1. 几个必要的概念

(1) 序列:姑且这么叫吧,即可根据位置或名字进行索引的数据结构,包括

  • 原子向量(各个值都是同类型的,包括 6 种类型:logical、integer、double、character、complex、raw,其中 integer 和 double 也统称为numeric)
  • 列表(各个值是不同类型的)

所谓循环迭代,就是依次在序列上做相同的操作。

(2) 泛函式编程:函数的函数称为泛函,在编程中表示函数作用在函数上,或者说函数包含其它函数作为参数。

循环迭代,本质上就是将一个函数依次应用(映射)到序列的每一个元素上。表示出来不就是泛函式:map(x, f)

(3) 管道:管道可以将数据从一个函数传给另一个函数,从而用若干函数构成的管道就能依次变换你的数据。例如:

x %>% f() %>% g()    # 等同于 g(f(x))

使用管道的好处是:提高程序可读性,避免引入不必要的中间变量。

对该管道示例应该这样理解:

依次对数据进行若干操作:先对 x 进行 f 操作, 接着对结果进行 g 操作

注:数据经过管道默认传递给函数的第一个参数(表现为省略);若在非第一个参数处使用该数据,用 "." 代替,这使得管道作用更加强大和灵活。

2. 循环迭代返回类型的控制

map 系列函数都有后缀形式,以决定循环迭代之后返回的数据类型,这是 purrr 比 apply函数族更先进和便利的一大优势。常用后缀如下:

  • map_chr(.x, .f): 返回字符型向量
  • map_lgl(.x, .f): 返回逻辑型向量
  • map_dbl(.x, .f): 返回实数型向量
  • map_int(.x, .f): 返回整数型向量
  • map_dfr(.x, .f): 返回数据框列表,再 bind_rows 按行合并为一个数据框
  • map_dfc(.x, .f): 返回数据框列表,再 bind_cols 按列合并为一个数据框

3. purrr 风格公式(匿名函数)

在序列上做循环迭代(应用函数),经常需要自定义函数,但有些简单的函数也用 function 定义一番,毕竟是麻烦和啰嗦。所以,purrr 包提供了对 purrr 风格公式(匿名函数)的支持。

熟悉其它语言的匿名函数的话,很自然地就能习惯。

前面说了,purrr 包实现迭代循环是用 map(x, f),f 是要应用的函数,想用匿名函数来写它,它要应用在序列 x 上,就是要和序列 x 相关联,那么就限定用序列参数名关联好了,即将该序列参数名 作为匿名函数的参数使用

  • 一元函数:序列参数是 .x

比如,f(x) = x^2 + 1, 其 purrr 风格公式(匿名函数)就写为:~ .x ^ 2 + 1

  • 二元函数:序列参数是 .x, .y

比如,f(x, y) = x^2 - 3 y, 其 purrr 风格公式(匿名函数)就写为:~ .x ^ 2 - 3 * .y

  • 多元函数:序列参数是 ..1, ..2, ..3, 等

比如,f(x, y, z) = ln(x + y + z), 其 purrr 风格公式(匿名函数)就写为:~ log(..1 + ..2 + ..3)

:所有序列参数,可以用 ... 代替,比如,sum(..1, ..2, ..3) 同 sum(...)

二. map(): 依次应用一元函数到一个序列的每个元素上

map(.x, .f, ...)
map_*(.x, .f, ...)

其中,.x 为序列

.f 为要应用的一元函数,或 purrr 风格公式(匿名函数)

... 可设置函数 .f 的其它参数

cb40daa6cdabb73f5d59d33976b42a16.png

例1 计算 iris 前4列,每列的均值

即依次将 mean() 函数,应用到第1列,第2列,...

df = iris[, 1:4]
map(df, mean)

  • 5
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值