如何控制 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
中使用控制流参数。尽管即使 FLAG
是 FALSE
也会 运行 代码,然后将 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 .
}
我想你会同意这相当复杂:
- 将
{…}
的右侧换行会禁用 %>%
的常规参数替换。相反,您将明确需要使用 .
。这允许我们在这里使用if
。
- 但是我们不能只写
. %>% mutate(…)
,因为句法序列. %>% …
不执行通常的管道;相反,它创建了一个 匿名函数 。为了防止这种情况(并恢复常规管道功能),我们需要将左侧包装成 (…)
.
可以这么说,我不推荐写这个。我推荐使用函数。
如果我有这样的数据框:
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
中使用控制流参数。尽管即使 FLAG
是 FALSE
也会 运行 代码,然后将 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 .
}
我想你会同意这相当复杂:
- 将
{…}
的右侧换行会禁用%>%
的常规参数替换。相反,您将明确需要使用.
。这允许我们在这里使用if
。 - 但是我们不能只写
. %>% mutate(…)
,因为句法序列. %>% …
不执行通常的管道;相反,它创建了一个 匿名函数 。为了防止这种情况(并恢复常规管道功能),我们需要将左侧包装成(…)
.
可以这么说,我不推荐写这个。我推荐使用函数。