改变多个变量以创建多个新变量

Jac*_*son 5 r dplyr tidyverse tidyselect

假设我有一个tibble需要采取多个变量并将它们变为新的多个新变量的位置.

举个例子,这是一个简单的tibble:

tb <- tribble(
  ~x, ~y1, ~y2, ~y3, ~z,
  1,2,4,6,2,
  2,1,2,3,3,
  3,6,4,2,1
)
Run Code Online (Sandbox Code Playgroud)

我想从名称以"y"开头的每个变量中减去变量z,并将结果变为tb的新变量.另外,假设我不知道我有多少"y"变量.我希望解决方案能够很好地适应tidyverse/ dplyr工作流程.

本质上,我不明白如何将多个变量变为多个新变量.我不确定你是否可以mutate在这个例子中使用?我试过了mutate_if,但我不认为我正确使用它(我收到错误):

tb %>% mutate_if(starts_with("y"), funs(.-z))

#Error: No tidyselect variables were registered
Run Code Online (Sandbox Code Playgroud)

提前致谢!

Tun*_*ung 12

因为您正在操作列名,所以您需要使用mutate_at而不是mutate_if使用列中的值

tb %>% mutate_at(vars(starts_with("y")), funs(. - z))
#> # A tibble: 3 x 5
#>       x    y1    y2    y3     z
#>   <dbl> <dbl> <dbl> <dbl> <dbl>
#> 1     1     0     2     4     2
#> 2     2    -2    -1     0     3
#> 3     3     5     3     1     1
Run Code Online (Sandbox Code Playgroud)

要创建新列,而不是覆盖现有列,我们可以给出名称 funs

# add suffix
tb %>% mutate_at(vars(starts_with("y")), funs(mod = . - z))
#> # A tibble: 3 x 8
#>       x    y1    y2    y3     z y1_mod y2_mod y3_mod
#>   <dbl> <dbl> <dbl> <dbl> <dbl>  <dbl>  <dbl>  <dbl>
#> 1     1     2     4     6     2      0      2      4
#> 2     2     1     2     3     3     -2     -1      0
#> 3     3     6     4     2     1      5      3      1

# remove suffix, add prefix
tb %>%
  mutate_at(vars(starts_with("y")),  funs(mod = . - z)) %>%
  rename_at(vars(ends_with("_mod")), funs(paste("mod", gsub("_mod", "", .), sep = "_")))
#> # A tibble: 3 x 8
#>       x    y1    y2    y3     z mod_y1 mod_y2 mod_y3
#>   <dbl> <dbl> <dbl> <dbl> <dbl>  <dbl>  <dbl>  <dbl>
#> 1     1     2     4     6     2      0      2      4
#> 2     2     1     2     3     3     -2     -1      0
#> 3     3     6     4     2     1      5      3      1
Run Code Online (Sandbox Code Playgroud)

编辑:在dplyr 0.8.0或更高版本,funs()将被弃用(来源1源2),需要使用list()替代

tb %>% mutate_at(vars(starts_with("y")), list(~ . - z))
#> # A tibble: 3 x 5
#>       x    y1    y2    y3     z
#>   <dbl> <dbl> <dbl> <dbl> <dbl>
#> 1     1     0     2     4     2
#> 2     2    -2    -1     0     3
#> 3     3     5     3     1     1

tb %>% mutate_at(vars(starts_with("y")), list(mod = ~ . - z))
#> # A tibble: 3 x 8
#>       x    y1    y2    y3     z y1_mod y2_mod y3_mod
#>   <dbl> <dbl> <dbl> <dbl> <dbl>  <dbl>  <dbl>  <dbl>
#> 1     1     2     4     6     2      0      2      4
#> 2     2     1     2     3     3     -2     -1      0
#> 3     3     6     4     2     1      5      3      1

tb %>%
  mutate_at(vars(starts_with("y")),  list(mod = ~ . - z)) %>%
  rename_at(vars(ends_with("_mod")), list(~ paste("mod", gsub("_mod", "", .), sep = "_")))
#> # A tibble: 3 x 8
#>       x    y1    y2    y3     z mod_y1 mod_y2 mod_y3
#>   <dbl> <dbl> <dbl> <dbl> <dbl>  <dbl>  <dbl>  <dbl>
#> 1     1     2     4     6     2      0      2      4
#> 2     2     1     2     3     3     -2     -1      0
#> 3     3     6     4     2     1      5      3      1
Run Code Online (Sandbox Code Playgroud)

reprex包创建于2018-10-29 (v0.2.1)

  • 谢谢!那么,如果我想让它们成为新变量,而不是更改现有变量呢?那么 8 列小标题而不是 5 列?这就是我所追求的。 (2认同)