如何控制 dplyr/tidyr 序列

How to control a dplyr/tidyr sequence

如果我有这样的数据框:

library(tidyverse)
set.seed(1234)
d <- tibble(a = sample(letters[1:3], 10, replace = TRUE), x = rnorm(10, 10, 2))

我想改变变量 x,但前提是常量 FLAG 为真:

FLAG <- TRUE

有没有比这样定义函数更简单的方法:

my_fun <- function(d, flag = FLAG) {
  if (flag) {
    d %>%
      mutate(x = x * 1000)
  } else {
    d
  }
}

d %>%
  my_fun # works, but function is defined "somewhere else"

我知道你的意图是什么,但你可以在 mutate 中使用控制流参数。尽管即使 FLAGFALSE 也会 运行 代码,然后将 x 分配给 x 本身。所以你也可以将整个语句包装在一个控制流中。

library(dplyr)

d <- tibble(a = sample(letters[1:3], 10, replace = TRUE), x = rnorm(10, 10, 2))

FLAG <- TRUE

d %>% 
  mutate(x = if (FLAG) x*1000 else x)
#> # A tibble: 10 x 2
#>    a          x
#>    <chr>  <dbl>
#>  1 a     12818.
#>  2 b     12887.
#>  3 a     15595.
#>  4 a      9171.
#>  5 a      9145.
#>  6 b     12277.
#>  7 a      9361.
#>  8 b     12260.
#>  9 a     11307.
#> 10 b      7182.

reprex package (v0.3.0)

于 2021-06-09 创建

或者计算效率更高,因为代码只有 运行 当 FLAG == TRUE 否则 d 不变。

if (FLAG) d <- mutate(d, x = x*1000)

更新

如果您打算将常规 if 语句集成到管道中,那么 Github 上有 {mpipe} 包,它有一个名为 if_branch 的函数。这是一个示例,其中 FLAG 设置为 FALSE:

library(dplyr)
library(mpipe)

d <- tibble(a = sample(letters[1:3], 10, replace = TRUE), x = rnorm(10, 10, 2))

FLAG <- FALSE

# x is left unchanged, but the pipe continuous:
d %>% 
  if_branch(FLAG,
            . %>% mutate(x = x * 1000)) %>% 
  mutate(new = 1) # pipe continuous
#> # A tibble: 10 x 3
#>    a         x   new
#>    <chr> <dbl> <dbl>
#>  1 a     11.3      1
#>  2 b     14.4      1
#>  3 b      9.83     1
#>  4 c      7.56     1
#>  5 b      5.89     1
#>  6 a      8.76     1
#>  7 a     13.9      1
#>  8 c     11.4      1
#>  9 c     10.2      1
#> 10 c     10.6      1

reprex package (v0.3.0)

于 2021-06-09 创建

函数是 R 中的基本抽象单元。请自由使用它们。

也就是说,如果您想在管道中内联选择,您可以执行以下操作:

d %>% {
    if (flag) (.) %>% mutate(x = x * 100) else .
}

我想你会同意这相当复杂:

  1. {…} 的右侧换行会禁用 %>% 的常规参数替换。相反,您将明确需要使用 .。这允许我们在这里使用if
  2. 但是我们不能只写. %>% mutate(…),因为句法序列. %>% …不执行通常的管道;相反,它创建了一个 匿名函数 。为了防止这种情况(并恢复常规管道功能),我们需要将左侧包装成 (…).

可以这么说,我推荐写这个。我推荐使用函数。