美文网首页
87.关于map()函数系列

87.关于map()函数系列

作者: 心惊梦醒 | 来源:发表于2021-11-21 14:30 被阅读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()族函数的简单比较】

    相关文章

      网友评论

          本文标题:87.关于map()函数系列

          本文链接:https://www.haomeiwen.com/subject/ndezzltx.html