Loading [MathJax]/jax/output/CommonHTML/config.js
前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >「R」用purrr实现迭代

「R」用purrr实现迭代

作者头像
王诗翔呀
发布于 2020-07-03 09:48:51
发布于 2020-07-03 09:48:51
5K00
代码可运行
举报
文章被收录于专栏:优雅R优雅R
运行总次数:0
代码可运行

本文来源于 2018 年学习《R for Data Science》写的笔记。一起复习一下吧~

函数有3个好处:

  • 更容易看清代码意图
  • 更容易对需求变化做出反应(改变)
  • 更容易减少程序bug

除了函数,减少重复代码的另一种工具是迭代,它的作用在于可以对多个输入执行同一种处理,比如对多个列或多个数据集进行同样的操作。

迭代方式主要有两种:

  • 命令式编程 - for和while
  • 函数式编程 - purrr
准备工作

purrr是tidyverse的核心r包之一,提供了一些更加强大的编程工具。(读者可以点击原文获取小抄

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
library(tidyverse)
#> ─ Attaching packages ─────────────────────────────────────────────────── tidyverse 1.2.1 ─
#> ✔ ggplot2 3.0.0     ✔ purrr   0.2.5
#> ✔ tibble  1.4.2     ✔ dplyr   0.7.6
#> ✔ tidyr   0.8.1     ✔ stringr 1.3.1
#> ✔ readr   1.1.1     ✔ forcats 0.3.0
#> ─ Conflicts ──────────────────────────────────────────────────── tidyverse_conflicts() ─
#> ✖ dplyr::filter() masks stats::filter()
#> ✖ dplyr::lag()    masks stats::lag()

for循环与函数式编程

因为R是一门函数式编程语言,我们可以先将for循环包装在函数中,然后再调用函数,而不是使用for循环,因此for循环在R中不像在其他编程语言中那么重要。

为了说明函数式编程,我们先利用下面简单的数据框进行一些思考:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
df = tibble(
    a = rnorm(10),
    b = rnorm(10),
    c = rnorm(10),
    d = rnorm(10)
)

如果想要计算每列的均值,我们使用for循环完成任务:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
output = vector("double", length(df))

for (i in seq_along(df)) {
    output[[i]] = mean(df[[i]])
}

output
#> [1]  0.45635 -0.17938  0.32879  0.00263

然后我们可能意识到需要频繁地计算每列的均值,因此将代码提取出来,转换为一个函数:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
col_mean = function(df) {
    output = vector("double", length(df))
    for ( i in seq_along(df)) {
        output[i] = mean(df[[i]])
    }
    
    output
}

然后我们觉得可能还需要这样计算每列的中位数和标准差,因此复制粘贴了col_mean(),并使用相应的median()sd()函数替换了mean()函数:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
col_median = function(df) {
    output = vector("double", length(df))
    for ( i in seq_along(df)) {
        output[i] = median(df[[i]])
    }
    
    output
}

col_sd = function(df) {
    output = vector("double", length(df))
    for ( i in seq_along(df)) {
        output[i] = sd(df[[i]])
    }
    
    output
}

(有时候我还真这么干的。)

哎呀,我们又复制粘贴了2次代码,因此是不是该思考下如何扩展一个代码让它同时发挥几个函数的功能呢?这段代码的大部分是一个for循环,而且如果不仔细很难看出3个函数有什么差别。

通过添加支持函数到每列的参数,我们可以使用同一个函数解决3个问题:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
col_summary = function(df, fun){
    out = vector("double", length(df))
    for (i in seq_along(df)) {
        out[i] = fun(df[[i]])
    }
    out
}

col_summary(df, median)
#> [1] 0.4666 0.0269 0.6161 0.0573
col_summary(df, mean)
#> [1]  0.45635 -0.17938  0.32879  0.00263

将函数作为参数传入另一个函数的做法是一种非常强大的功能,我们需要花些时间理解这种思想,但绝对是值得的。接下来我们将学习和使用purrr包,它提供的函数可以替代很多常见的for循环应用。R基础包中的apply应用函数族也可以完成类似的任务,但purrr包的函数更一致,也更容易学习。

使用purrr函数替代for循环的目的是将常见的列表问题分解为独立的几部分

  • 对于列表的单个元素,我们能找到解决办法吗?如果可以,我们就能使用purrr将该方法扩展到列表的所有元素。
  • 如果我们面临的是一个复杂的问题,那么将其分解为可行的子问题,然后依次解决。使用purrr,我们可以解决子问题,然后用管道将其组合起来。

映射函数

先对向量进行循环,然后对其每一个元素进行一番处理,最后保存结果。这种模式太普遍了,因而purrr包提供了一个函数族替我们完成这种操作。每种类型的输出都有一个相应的函数:

  • map()用于输出列表
  • map_lgl()用于输出逻辑型向量
  • map_dbl()用于输出双精度型向量
  • map_chr()用于输出字符型向量

每个函数都使用一个向量(注意列表可以作为递归向量看待)作为输入,并对向量的每个元素应用一个函数,然后返回和输入向量同样长度的一个新向量。向量的类型由映射函数的后缀决定。

使用map()函数族的优势不是速度,而是简洁:它可以让我们的代码更易编写,也更易阅读。

下面是进行上一节一样的操作:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
library(purrr)

map_dbl(df, mean)
#>        a        b        c        d 
#>  0.45635 -0.17938  0.32879  0.00263
map_dbl(df, median)
#>      a      b      c      d 
#> 0.4666 0.0269 0.6161 0.0573
map_dbl(df, sd)
#>     a     b     c     d 
#> 0.608 1.086 0.797 0.873

**与for循环相比,映射函数的重点在于需要执行的操作(即mean()median()sd()),而不是在所有元素中循环所需的跟踪记录以及保存结果。使用管道时这一点尤为突出:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
df %>% map_dbl(mean)
#>        a        b        c        d 
#>  0.45635 -0.17938  0.32879  0.00263
df %>% map_dbl(median)
#>      a      b      c      d 
#> 0.4666 0.0269 0.6161 0.0573
df %>% map_dbl(sd)
#>     a     b     c     d 
#> 0.608 1.086 0.797 0.873

map_*()col_summary()具有以下几点区别:

  • 所有的purrr函数都是用C实现的,这让它们的速度非常快,但牺牲了一些可读性。
  • 第二个参数可以是一个公式、一个字符向量或一个整型向量。
  • map_*()使用....f传递一些附加参数,供每次调用时使用
  • 映射函数还保留名称

快捷方式

对于第二个参数.f,我们可以使用几种快捷方式来减少输入量。比如我们现在想对某个数据集中的每一个分组都拟合一个线性模型,下面示例将mtcars数据集拆分为3个部分(按照气缸值分类),并对每个部分拟合一个线性模型:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
models = mtcars %>% 
    split(.$cyl) %>% 
    map(function(df) lm(mpg ~ wt, data = df))

因为在R中创建匿名函数的语法比较复杂,所以purrr提供了一种更方便的快捷方式——单侧公式:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
models = mtcars %>% 
    split(.$cyl) %>% 
    map(~lm(mpg ~ wt, data = .))

上面.作为一个代词:它表示当前列表元素(与for循环中用i表示当前索引是一样的)。

当检查多个模型时,有时候我们需要提取像R方这样的摘要统计量,要想完成这个任务,我们需要先运行summary()函数,然后提取结果中的r.squared:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
models %>% 
    map(summary) %>% 
    map_dbl(~.$r.squared)
#>     4     6     8 
#> 0.509 0.465 0.423

因为提取命名成分操作非常普遍,所以purrr提供了一种更简单的快捷方式:使用字符串。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
models %>% 
    map(summary) %>% 
    map_dbl("r.squared")
#>     4     6     8 
#> 0.509 0.465 0.423

对操作失败的处理

当使用映射函数重复多次操作时,某次操作失败的概率大大增加。这个时候我们会收到一条错误信息,但得不到任何结果。这让人很恼火!我们怎么保证不会出现一条鱼腥了一锅汤?

safely()是一个修饰函数(副词),它接收一个函数(动词),对其进行修改并返回修改后的函数。这样,修改后的函数就不会抛出错误,相反,它总是返回由下面两个元素组成的列表:

  • result - 原始结果。如果出现错误,那么它就是NULL
  • error - 错误对象。如果操作成功,那么它就是NULL

下面用log()函数进行说明:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
safe_log = safely(log)
str(safe_log(10))
#> List of 2
#>  $ result: num 2.3
#>  $ error : NULL

str(safe_log("a"))
#> List of 2
#>  $ result: NULL
#>  $ error :List of 2
#>   ..$ message: chr "数学函数中用了非数值参数"
#>   ..$ call   : language log(x = x, base = base)
#>   ..- attr(*, "class")= chr [1:3] "simpleError" "error" "condition"

safely()函数也可以与map()共同使用:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
x = list(1, 10, "a")
y = x %>% map(safely(log))
str(y)
#> List of 3
#>  $ :List of 2
#>   ..$ result: num 0
#>   ..$ error : NULL
#>  $ :List of 2
#>   ..$ result: num 2.3
#>   ..$ error : NULL
#>  $ :List of 2
#>   ..$ result: NULL
#>   ..$ error :List of 2
#>   .. ..$ message: chr "数学函数中用了非数值参数"
#>   .. ..$ call   : language log(x = x, base = base)
#>   .. ..- attr(*, "class")= chr [1:3] "simpleError" "error" "condition"

如果将以上结果转换为2个列表,一个列表包含所有错误对象,另一个列表包含所有原始结果,那么处理起来就会更容易。我们可以使用purrr::transpose()函数轻松完成该任务

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
y = y %>% transpose()
str(y)
#> List of 2
#>  $ result:List of 3
#>   ..$ : num 0
#>   ..$ : num 2.3
#>   ..$ : NULL
#>  $ error :List of 3
#>   ..$ : NULL
#>   ..$ : NULL
#>   ..$ :List of 2
#>   .. ..$ message: chr "数学函数中用了非数值参数"
#>   .. ..$ call   : language log(x = x, base = base)
#>   .. ..- attr(*, "class")= chr [1:3] "simpleError" "error" "condition"

我们可以自行决定如何处理错误对象,一般来说,我们应该检查一下y中错误对象所对应的x值,或者使用y中的正常结果进行一些处理:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
is_ok = y$error %>% map_lgl(is_null)
x[!is_ok]
#> [[1]]
#> [1] "a"

y$result[is_ok] %>% flatten_dbl()
#> [1] 0.0 2.3

purrr还提供了两个有用的修饰函数:

  • safely()类似,possibly()函数总是会成功返回。它比safely()还要简单一些,因为可以设定出现错误时返回一个默认值:
代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
x = list(1, 10, "a")
x %>% map_dbl(possibly(log, NA_real_))
#> [1] 0.0 2.3  NA
  • quietly()函数与safely()的作用基本相同,但前者结果不包含错误对象,而是包含输出、消息和警告:
代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
x = list(1, -1)
x %>% map(quietly(log)) %>% str()
#> List of 2
#>  $ :List of 4
#>   ..$ result  : num 0
#>   ..$ output  : chr ""
#>   ..$ warnings: chr(0) 
#>   ..$ messages: chr(0) 
#>  $ :List of 4
#>   ..$ result  : num NaN
#>   ..$ output  : chr ""
#>   ..$ warnings: chr "产生了NaNs"
#>   ..$ messages: chr(0)

x %>% map(safely(log)) %>% str()
#> Warning in .f(...): 产生了NaNs
#> List of 2
#>  $ :List of 2
#>   ..$ result: num 0
#>   ..$ error : NULL
#>  $ :List of 2
#>   ..$ result: num NaN
#>   ..$ error : NULL

多参数映射

前面我们提到的映射函数都是对单个输入进行映射,但有时候我们需要多个相关输入同步迭代,这就是map2()和pmap()函数的用武之地

例如我们想模拟几个均值不同的随机正态分布,我们可以使用map完成这个任务:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
mu = list(5, 10, -3)
mu %>% 
    map(rnorm, n = 5) %>% 
    str()
#> List of 3
#>  $ : num [1:5] 5.65 6.48 6.35 4.61 4.74
#>  $ : num [1:5] 8.93 8.93 10.67 10.98 8.72
#>  $ : num [1:5] -4.04 -3.25 -2.16 -3.02 -2.53

如果我们想让标准差也不同,一种方法是使用均值向量和标准差向量的索引进行迭代:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
sigma = list(1, 5, 10)
seq_along(mu) %>% 
    map(~rnorm(5, mu[[.]], sigma[[.]])) %>% 
    str()
#> List of 3
#>  $ : num [1:5] 4.5 4.73 4.43 6.19 5.47
#>  $ : num [1:5] 8.71 8.59 18.26 7.93 4.93
#>  $ : num [1:5] -21.46 -7.94 -21.41 5.66 2.38

但这种方式比较难理解,我们使用map2()进行同步迭代:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
map2(mu, sigma, rnorm, n = 5) %>% str()
#> List of 3
#>  $ : num [1:5] 6.08 6.72 7.59 5.21 3.99
#>  $ : num [1:5] 13.44 6.81 3.61 22.29 14.29
#>  $ : num [1:5] 4.05 -1.77 -2.77 0.69 -23.91

注意这里每次调用时值发生变换的参数要放在映射函数前面,值不变的参数要放在映射函数后面。

map()函数一样,map2()函数也是对for循环的包装:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
map2 = function(x, y, f, ...){
    out = vector("list", length(x))
    for (i in seq_along(x)) {
        out[[i]] = f(x[[i]], y[[i]], ...)
    }
    out
}

(实际的map2()并不是这样的,此处是给出R实现的一种思想)

根据这个函数,我们可以涉及map3()map4()等等,但这样实在无聊。purrr提供了pmap()函数,它可以将列表作为参数。如果我们想要生成均值、标准差和样本数都不同的正态分布,可以使用:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
n = list(1, 3, 5)
args1 = list(n, mu, sigma)

args1 %>% 
    pmap(rnorm) %>% 
    str()
#> List of 3
#>  $ : num 3.55
#>  $ : num [1:3] 8.4 10.9 -3.3
#>  $ : num [1:5] 3.9 -11.61 2.06 7.14 -16.25

如果没有为列表元素命名,那么pmap()在调用函数时会按照位置匹配。这样做容易出错而且可读性差,因此最后使用命名参数:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
args2 = list(mean = mu, sd = sigma, n = n)
args2 %>% 
    pmap(rnorm) %>% 
    str()
#> List of 3
#>  $ : num 6.18
#>  $ : num [1:3] 11.2 18 14.8
#>  $ : num [1:5] -5.27 6.57 1.88 6.53 -8.35

这样更加安全。

因为长度都相同,所以将各个参数保存在一个数据框中:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
params = tibble::tribble(
    ~mean, ~sd, ~n,
    5, 1, 1,
    10, 5, 3,
    -3, 10, 5
)

params %>% 
    pmap(rnorm)
#> [[1]]
#> [1] 5.41
#> 
#> [[2]]
#> [1]  5.4 10.2 14.4
#> 
#> [[3]]
#> [1] -8.653 -4.457  9.747 -4.916 -0.436
调用不同的函数

还有一种更复杂的情况:不但传给函数的参数不同,甚至函数本身也是不同的。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
f = c("runif", "rnorm", "rpois")
param = list(
    list(min = -1, max = 1),
    list(sd = 5),
    list(lambda = 10)
)

为了处理这种情况,我们使用invoke_map()函数:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
invoke_map(f, param, n = 5) %>% str()
#> List of 3
#>  $ : num [1:5] 0.167 -0.235 -0.366 -0.933 0.304
#>  $ : num [1:5] 6.961 3.642 13.405 0.536 -2.078
#>  $ : int [1:5] 8 8 8 6 11

第1个参数是一个函数列表或包含函数名称的字符串向量。第2个参数是列表的一个列表,给出了要传给各个函数的不同参数。随后的参数要传给每个函数

我们使用tribble()让参数配对更容易:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
sim = tibble::tribble(
    ~f, ~params,
    "runif", list(min = -1, max = 1),
    "rnorm", list(sd = 5),
    "rpois", list(lambda = 10)
)


sim %>% 
    dplyr::mutate(sim = invoke_map(f, params, n = 10))
#> # A tibble: 3 x 3
#>   f     params     sim       
#>   <chr> <list>     <list>    
#> 1 runif <list [2]> <dbl [10]>
#> 2 rnorm <list [1]> <dbl [10]>
#> 3 rpois <list [1]> <int [10]>

游走函数

当使用函数的目的是向屏幕提供输出或将文件保存到磁盘——重要的是操作过程而不是返回值,我们应该使用游走函数,而不是映射函数。

下面是一个示例:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
x = list(1, "a", 3)

x %>% 
    walk(print)
#> [1] 1
#> [1] "a"
#> [1] 3

一般来说,walk()函数不如walk2()和pwalk()实用。例如有一个图形列表和一个文件名向量,那么我们就可以使用pwalk()将每个文件保存到相应的磁盘位置:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
library(ggplot2)

plots = mtcars %>% 
    split(.$cyl) %>% 
    map(~ggplot(., aes(mpg, wt)) + geom_point())
paths = stringr::str_c(names(plots), ".pdf")

pwalk(list(paths, plots), ggsave, path = tempdir())
#> Saving 7 x 5 in image
#> Saving 7 x 5 in image
#> Saving 7 x 5 in image

我们来查看一下是不是建立好了:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
dir(tempdir())
#> [1] "4.pdf" "6.pdf" "8.pdf"

for循环的其他模式

purrr还提供了其他一些函数,虽然这些函数的使用率低,但了解还是有必要的。本节就是对它们进行简单介绍

预测函数

一些函数可以与返回TRUEFALSE的预测函数一同使用。

keep()discard()函数可以分别保留输入中预测值为TRUEFALSE的元素(在数据框中就是指列):

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
iris %>% 
    keep(is.factor) %>% 
    str()
#> 'data.frame':    150 obs. of  1 variable:
#>  $ Species: Factor w/ 3 levels "setosa","versicolor",..: 1 1 1 1 1 1 1 1 1 1 ...


iris %>% 
    discard(is.factor) %>% 
    str()
#> 'data.frame':    150 obs. of  4 variables:
#>  $ Sepal.Length: num  5.1 4.9 4.7 4.6 5 5.4 4.6 5 4.4 4.9 ...
#>  $ Sepal.Width : num  3.5 3 3.2 3.1 3.6 3.9 3.4 3.4 2.9 3.1 ...
#>  $ Petal.Length: num  1.4 1.4 1.3 1.5 1.4 1.7 1.4 1.5 1.4 1.5 ...
#>  $ Petal.Width : num  0.2 0.2 0.2 0.2 0.2 0.4 0.3 0.2 0.2 0.1 ...

some()every()函数分别用来确定预测值是否对某个元素为真以及是否对所有元素为真:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
x = list(1:5, letters, list(10))


x %>% 
    some(is_character)
#> [1] TRUE

x %>% 
    every(is_vector)
#> [1] TRUE

detect()可以找出预测值为真的第一个元素,detect_index()可以返回该元素的索引。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
x = sample(10)
x
#>  [1] 10  8  5  7  4  1  2  9  3  6

x %>% 
    detect(~ . >5)
#> [1] 10

x %>% 
    detect_index(~ . >5)
#> [1] 1

head_while()tail_while()分别从向量的开头和结尾找出预测值为真的元素:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
x %>% 
    head_while(~ . > 5)
#> [1] 10  8

x %>% 
    tail_while(~ . > 5)
#> [1] 6

归约和累计

操作一个复杂的列表,有时候我们想要不断合并两个预算两个元素(基础函数Reduce干的事情)。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
dfs = list(
    age = tibble(name = "John", age = 30),
    sex = tibble(name = c("John", "Mary"), sex = c("M", "F")),
    trt = tibble(name = "Mary", treatment = "A")
)

dfs %>% reduce(full_join)
#> Joining, by = "name"
#> Joining, by = "name"
#> # A tibble: 2 x 4
#>   name    age sex   treatment
#>   <chr> <dbl> <chr> <chr>    
#> 1 John     30 M     <NA>     
#> 2 Mary     NA F     A

这里我们使用reduce结合dplyr中的full_join()将它们轻松合并为一个数据框。

reduce()函数使用一个“二元函数”(即两个基本输入),将其不断应用于一个列表,直到最后只剩下一个元素。

累计函数与归约函数类似,但会保留中间结果,比如下面求取累计和:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
x = sample(10)

x
#>  [1]  9 10  8  5  6  2  3  4  7  1
x %>% accumulate(`+`)
#>  [1]  9 19 27 32 38 40 43 47 54 55
本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2020-05-07,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 优雅R 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
暂无评论
推荐阅读
编辑精选文章
换一批
R:purrr包用于循环迭代
purrr中有多个迭代函数,可以用于快速解决循环迭代的问题,purrr中常用的迭代函数有map、map2、walk、reduce等等。
生信菜鸟团
2020/07/16
1.8K0
「Workshop」第二十二期 purrr
以map开头的一系列函数接受向量为输入,对向量的每个元素进行函数运算,再返回一个新的向量,这个新的向量的长度和原来的一样长,向量元素的名称也是一样的;输出向量的类型由map函数的后缀来表明:
王诗翔呀
2022/01/21
7260
「Workshop」第二十二期 purrr
R语言实用技巧(1)R包检索
R语言数据分析指南
2024/05/07
3090
R语言实用技巧(1)R包检索
40. R 数据整理(十一: 用purrr包实现更花样的匿名函数使用)
其实map 除了对向量有用,也可以作用于数据框或矩阵类型,相当于把其中的每一列作为一个单独的元素来看,有点像按列的apply:
北野茶缸子
2021/12/17
2.8K0
R语言进阶笔记5 | purrr替代循环
其中,手动for循环我最常用,apply系列半吊子,purrr函数一窍不通,所以要学习一下。
邓飞
2021/01/12
3.4K0
「R」dplyr 行式计算
通常 dplyr 和 R 更适合对列进行操作,而对行操作则显得更麻烦。这篇文章,我们将学习围绕rowwise() 创建的 row-wise 数据框的 dplyr 操作方法。
王诗翔呀
2022/01/21
6.5K0
R包基础实操—tidyverse包
核心软件包是ggplot2、dplyr、tidyr、readr、purrr、tibble、stringr和forcats,它们提供了建模、转换和可视化数据的功能。
生信技能树jimmy
2021/10/11
3.6K0
R包基础实操—tidyverse包
R tips:使用enframe和map2优雅的迭代列表
在R中更易于处理的数据形式是data.frame,list并不是太好处理,常用操作就是对它进行循环迭代。
生信菜鸟团
2020/06/02
2K0
R-Purrr的使用,加速数据处理
Tidyverse中包含一个purrr程序包,之前在看数据处理分析时候,一直看到别人的code中,涵盖purrr,map函数,但是一直不知道这个是干什么的,现在发现purrr真的是极大的加速了数据处理流程,减少了code的编写。
Jamesjin63
2022/10/25
8020
我承认tidyverse已经脱离了R语言的范畴
最近知乎热议:R和Python谁更优雅的问题,或者谁更适合数据分析的问题,各种讨论,非常值得一看:
邓飞
2022/05/19
6880
我承认tidyverse已经脱离了R语言的范畴
「R」dplyr 列式计算
同时对数据框的多列执行相同的函数操作经常有用,但是通过拷贝和粘贴的方式进行的话既枯燥就容易产生错误。
王诗翔呀
2022/01/21
2.7K0
R语言倾向性评分:回归和分层
倾向性评分有4种应用,前面介绍了倾向性评分匹配及matchIt和cobalt包的使用:R语言倾向性评分:匹配
医学和生信笔记
2023/02/14
1.5K0
R语言倾向性评分:回归和分层
「R」tidyverse 中的公式函数
本文的写作由来是知识星球一个朋友对如何在 tidyverse 系列包中使用公式函数(单侧公式)不太熟悉,所以通过本文分享一下我的心得。
王诗翔呀
2021/01/03
4.5K0
「R」tidyverse 中的公式函数
37. R 茶话会(七:高效的处理数据框的列)
前言 这个笔记的起因是在学习DataExplorer 包的时候,发现: 这我乍一看,牛批啊。这语法还挺长见识的。 转念思考了一下🤔,其实目的也就是将数据框中的指定列转换为因子。换句话说,就是如何可以批量的对数据框的指定行或者列进行某种操作。(这里更多强调的是对原始数据框的直接操作,如果是统计计算直接找summarise 和它的小伙伴们,其他的玩意儿也各有不同,掉头左转: 34. R 数据整理(六:根据分类新增列的种种方法 1.0) 其实按照我的思路,还是惯用的循环了,对数据框的列名判断一下,如果所取的
北野茶缸子
2021/12/17
1.8K0
37. R 茶话会(七:高效的处理数据框的列)
p for trend/ p for interaction/ per 1 sd 的R语言实现
本篇主要介绍P for trend、p for interaction、per 1 sd的R语言实现,关于每一项的具体含义,可参考文中给出的链接,或者自己搜索学习。
医学和生信笔记
2023/02/14
1.4K0
独家 | 不同机器学习模型的决策边界(附代码)
本文利用Iris数据集训练了多组机器学习模型,并通过预测大量的拟合数据绘制出了每个模型的决策边界。
数据派THU
2020/04/14
2K0
独家 | 不同机器学习模型的决策边界(附代码)
R语言中list的批量操作
这个包的神奇之处在于能批量处理问题,例如,可以读取多个文件,跑模型的时候,可以批量输入多个参数,并把结果合并起来做比较
一粒沙
2022/06/07
2K0
R语言中list的批量操作
16. R编程(二:基本数据类型及其操作之因子、矩阵、数据框和列表)
使用rbind(),操作同cbind() 加和 colSums() 或 rowSums()
北野茶缸子
2021/12/17
2.9K0
16. R编程(二:基本数据类型及其操作之因子、矩阵、数据框和列表)
R语言亚组分析及森林图绘制
亚组分析的森林图很常见,在各种高分SCI文章中经常见到,其中我最喜欢NEJM的格式,美观,信息量也多。
医学和生信笔记
2023/08/30
1.9K0
R语言亚组分析及森林图绘制
tidyverse:R语言中相当于python中pandas+matplotlib的存在
tidyverse就是Hadley Wickham将自己所写的包整理成了一整套数据处理的方法,包括ggplot2、dplyr、tidyr、readr、purrr、tibble、stringr、forcats。出版有《R for Data Science》(中文版《R数据科学》),这本书详细介绍了tidyverse的使用方法。
拴小林
2021/01/12
4.8K0
相关推荐
R:purrr包用于循环迭代
更多 >
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档
本文部分代码块支持一键运行,欢迎体验
本文部分代码块支持一键运行,欢迎体验