R 语言 dplyr 包 1.1.0 版新功能之两个新函数(四) 您所在的位置:网站首页 r语言rchisq函数 R 语言 dplyr 包 1.1.0 版新功能之两个新函数(四)

R 语言 dplyr 包 1.1.0 版新功能之两个新函数(四)

2023-03-06 13:41| 来源: 网络整理| 查看: 265

dplyr 1.1.0 版本发布

2023/01/31 日,R 语言数据处理利器 dplyr 包的 1.1.0 版本正式发布。

对于这次更新,RStudio 官网十分重视,dplyr 包的开发者之一 Davis Vaughan,亲自在

连发 4 篇博客,对本次更新的内容进行了详细介绍,分为以下四个部分:

连接操作:join_by 新语法,涉及非等值连接、滚动连接、多值匹配的告警等分组操作:.by / by 参数的使用,比 group_by() 函数使用起来更方便,又略有不同更强大的函数:均由 vctrs 包支持,case_when()、case_match() 等函数的优化两个新函数:pick()reframe() 的用法,以及 arrange() 函数的改进

这篇文章,我们来看一下 dplyr 1.1.0 版本的两个新函数:pick()、reframe() 的用法,以及对 arrange() 函数在排序方面的改进。

1. pick() 函数

之前 dplyr 1.0.0 版本发布的时候,很多人喜欢使用 across() 函数来选择列,同时可以结合 summarise() 函数或者 mutate() 函数,比如统计数据框中以 x、y 开头的列的个数。

library(dplyr) df summarise( n_x = ncol(across(starts_with("x"))), n_y = ncol(across(starts_with("y"))) ) # # A tibble: 1 × 2 # n_x n_y # # 1 2 1

across() 函数的作用是用对每一列应用一个函数,而不仅仅是选择它们,但它的名字听起来不太自然。在 dplyr 1.1.0 中,新引入了 pick() 函数,专门用来选择列。

df |> summarise( n_x = ncol(pick(starts_with("x"))), n_y = ncol(pick(starts_with("y"))) ) # # A tibble: 1 × 2 # n_x n_y # # 1 2 1

pick() 函数在与 dense_rank() 等排序函数结合使用时特别有用,后者在 1.1.0 中进行了升级,可以将数据框作为输入,并实现对多列的组合排序。

df |> mutate( rank1 = dense_rank(x_1), rank2 = dense_rank(pick(x_1, y_2)) ) # # A tibble: 5 × 6 # x_1 x_2 w_4 y_2 rank1 rank2 # # 1 1 6 11 5 1 2 # 2 3 7 12 2 3 5 # 3 2 8 13 4 2 3 # 4 1 9 14 0 1 1 # 5 2 10 15 6 2 4

2. reframe() 函数

在进行分组操作时,每个分组一般返回的是一行数据,但在某些特殊情况下,每组返回多行结果是有必要的,但我们意识到 summarise() 函数并不是最佳选择。

举个例子,我想要计算 x 的平均值和标准偏差,按 g 分组。不幸的是,我不小心忘记使用 sd(x),而只是输入x,结果并没有报错,但最终的结果是 5 行而不是 2 行。

library(dplyr) df summarise( x_average = mean(x), x_sd = x, # Oops .by = g ) # # A tibble: 5 × 3 # g x_average x_sd # # 1 1 4.33 4 # 2 1 4.33 3 # 3 1 4.33 6 # 4 2 5 2 # 5 2 5 8 # Warning message: # Returning more (or less) than 1 row per `summarise()` group was deprecated in dplyr 1.1.0. # ℹ Please use `reframe()` instead. # ℹ When switching from `summarise()` to `reframe()`, remember that `reframe()` always returns an ungrouped data # frame and adjust accordingly.

而正确的结果应该为:

df |> summarise( x_average = mean(x), x_sd = sd(x), .by = g ) # # A tibble: 2 × 3 # g x_average x_sd # # 1 1 4.33 1.53 # 2 2 5 4.24

当任一分组返回的长度不为 1 时,summarise() 函数会抛出一个警告,未来会将此升级为错误,以保证每个分组返回的结果都是 1 行。

在收集了一些反馈后,我们确定了一个更适合这类操作的新函数 reframe()。reframe() 函数是对每个分组做一系列操作的一种方式,同时每个分组返回的行数也没有限制。这个函数的名字与 tibble 的两个函数 tibble::enframe() 和 tibble::deframe() 有很好的联系,它们用于在向量和数据框之间互相转化。

enframe():输入为向量,输出为数据框deframe():输入为数据框,输出为向量reframe():输入为数据框,输出为数据框

reframe() 函数的一个很好的应用是计算各种概率阈值的分位数。

quantile_df reframe(quantile_df(x), .by = g) # # A tibble: 6 × 3 # g value prob # # 1 1 3.5 0.25 # 2 1 4 0.5 # 3 1 5 0.75 # 4 2 3.5 0.25 # 5 2 5 0.5 # 6 2 6.5 0.75

如果你想使用 across() 函数将它应用到多个列上,也是可以的:

df |> reframe(across(x:y, quantile_df), .by = g) # # A tibble: 6 × 3 # g x$value $prob y$value $prob # # 1 1 3.5 0.25 1.5 0.25 # 2 1 4 0.5 2 0.5 # 3 1 5 0.75 3.5 0.75 # 4 2 3.5 0.25 8.25 0.25 # 5 2 5 0.5 8.5 0.5 # 6 2 6.5 0.75 8.75 0.75

3. arrange() 函数

arrange() 函数在 2 个方面进行了调整:

在对字符向量排序时,默认使用 C locale,而不是系统环境新增了一个新的 .locale 参数,由 stringi 包提供支持,允许使用 stringi 区域标识符显式指定语言环境(如 "en" 代表英语,“fr“ 代表法语)

如果你使用 arrange() 函数是为了将相似的值分组在一起,并且不太关心它使用的语言环境,那么在 dplyr 1.1.0中,性能会提高 100 倍,如果确实关心 locale 并指定了 .locale 的值,仍然能看到高达 10 倍的性能提升。

# 随机生成 1000000 个字符串 dictionary expression min median `itr/sec` mem_alloc `gc/sec` #> #> 1 arrange(str, x) 4.38s 4.89s 0.204 12.7MB 0.148 # dplyr 1.1.0 (C locale default, 100x faster) bench::mark(arrange(str, x)) #> # A tibble: 1 × 6 #> expression min median `itr/sec` mem_alloc `gc/sec` #> #> 1 arrange(str, x) 42.3ms 46.6ms 20.8 22.4MB 46.0 # dplyr 1.1.0 (American English `.locale`, 10x faster) bench::mark(arrange(str, x, .locale = "en")) #> # A tibble: 1 × 6 #> expression min median `itr/sec` mem_alloc #> #> 1 arrange(str, x, .locale = "en") 377ms 430ms 2.21 27.9MB #> # … with 1 more variable: `gc/sec`

希望默认切换到 C local 会产生相对较小的影响,以换取更快的性能。

参考网址:



【本文地址】

公司简介

联系我们

今日新闻

    推荐新闻

    专题文章
      CopyRight 2018-2019 实验室设备网 版权所有