87.关于map()函数系列

2021-11-21  本文已影响0人  心惊梦醒

【上一篇:86.关于split函数】
【下一篇:88.关于map()函数系列的shortcut以及于apply()族函数的简单比较】

    最常见的循环操作:对vector中的每个元素,执行某种操作后保存结果。purrr包中的map()函数系列可以帮助我们方便地完成这件事情,与Base R中的apply()族函数相比,map()函数系列是基于C的,因此计算比较快,但同时也牺牲了循环的可读性。

循环Vector中的每个元素

    map()函数系列包括:map()、map_lgl()、map_int()、map_dbl()、map_chr()、map_raw()、map_dfr()、map_dfc(),这些函数的功能都是一样的,输入都是List或atomic vector;map()函数的返回值是List;map_dfr()和map_dfc()的返回值是数据框;其他函数的返回值是atomic vector,且atomic vector中元素的类型由函数的名字指示。也就是说我们要根据应用到vector中每个元素的函数的返回值的类型选择对应的函数
    这些函数的Usage基本相同,仅map_dfr()函数有个.id参数,如下:

map(.x, .f, ...)
map_dfr(.x, .f, ..., .id = NULL)
输入参数

    .x:输入,可以是List或atomic vector。
    .f:应用的.x的每个元素的函数。1).f可以是R中已知的函数或自定义函数;2)可以是formula,诸如~ .x + 2这种形式的,这种情况将被转换成一个函数;3)也可以是character vector、numeric vector或list,这种情况将被转换成提取函数,即如果是character vector则根据name提取输入向量或列表的元素,如果是numeric vector则根据位置提取输入向量或列表的元素,如果需要同时用name和位置提取元素,则需要用列表表示。在提取元素时,如果对应位置处元素缺失,则可以通过设置.default参数表示缺失值。
    ...:传递给.f的其他参数。
    .id:仅用于map_dfr()函数中,字符串或NULL。若是字符串,输出将包含一个以.id为名字的变量,该变量指示input的name或index。若为NULL,则不会创建变量。

输出

    如果.x有names(),输出也会保留names。
    输出的长度必等于输入的长度。

举例说明
# 下面这三种写法是等价的
> 1:10 %>%
  map(rnorm, n = 10)
> 1:10 %>%
  map(function(x) rnorm(10, x))
> 1:10 %>%
  map(~ rnorm(10, .x))

# 提取函数
l2 <- list(
  list(num = 1:3,     letters[1:3]),
  list(num = 101:103, letters[4:6]),
  list()
)
# 提取l2中以num为名字的元素,缺失值用???代替
l2 %>% map("num", .default = "???")
# 提取l2中每个元素中第一个位置处的元素,却缺失值用NA代替
l2 %>% map_int(1, .default = NA)
# 提取l2中每个元素中以"num"命名的元素中的第一个元素
l2 %>% map(list("num",1))
# 等效与这种写法
l2 %>% map(list(1,1))

# 如果输出的每个元素是数据框,可以用map_dfr()进行行合并
mtcars %>%
  split(.$cyl) %>%
  map(~ lm(mpg ~ wt, data = .x)) %>%
  map_dfr(~ as.data.frame(t(as.matrix(coef(.)))))

有条件地循环Vector中的每个元素

    这样的函数包括:map_if()、map_at()、map_depth(),只有满足指定的某种条件的元素才会被应用指定的函数。

# p为predicate function
map_if(.x, .p, .f, ..., .else = NULL)
map_at(.x, .at, .f, ...)
map_depth(.x, .depth, .f, ..., .ragged = FALSE)

    map_if()和map_at()函数接受.x作为输入,将.f应用到.x中的一些元素上,返回与.x长度一致的列表。map_if()接受一个.p函数作为输入,决定.x中的哪些元素用.f转换。map_at()接受一个.at向量(names或positions)决定.x中的哪些元素用.f转换。
    map_depth()允许对nested vector的特定level应用.f。

输入参数

    .x:List或atomic vector。
    .p:可以是:1)a single predicate funtion(判定函数);2)一个描述predicate function的formula;3)与.x等长的逻辑向量。总得来说就是,.x应用.p之后返回一个与.x等长的逻辑向量,只有评估为TRUE的元素才会被应用.f函数。
    .else:一个函数。评估为FALSE的元素将被应用.else指定的函数。
    .f:同上。
    .at:character vector:元素的names;positive numeric vector:元素的位置;negative numeric vector:被去除的元素的位置。
    .depth:数字,指示在哪个level应用.f。
    map_depth(x, 0, fun)等价于fun(x)
    map_depth(x, 1, fun)等价于x <- map(x, fun)
    map_depth(x, 2, fun)等价于x <- map(x, ~ map(., fun))

输出

    若.else为NULL,评估为TRUE的元素返回应用.f后的结果,评估为FLASE的元素原样输出。

举例说明
# iris中,因子列应用as.character,其他列应用as.integer
> map_if(iris, is.factor, as.character, .else = as.integer)
# 指定位置处应用is.numeric函数
> iris %>% map_at(c(4, 5), is.numeric)
# 指定name应用toupper
> iris %>% map_at("Species", toupper)
# map_depth暂不举例

【上一篇:86.关于split函数】
【下一篇:88.关于map()函数系列的shortcut以及于apply()族函数的简单比较】

上一篇下一篇

猜你喜欢

热点阅读