首页 > 解决方案 > 使用 `mutate` 和 `across` 时如何保留旧列并重命名新列

问题描述

当我mutate across数据时,选择的列被.cols突变的结果替换。在以下情况下如何执行此操作:

例如:

require(dplyr)
#> Loading required package: dplyr
#> 
#> Attaching package: 'dplyr'
#> The following objects are masked from 'package:stats':
#> 
#>     filter, lag
#> The following objects are masked from 'package:base':
#> 
#>     intersect, setdiff, setequal, union
require(magrittr)
#> Loading required package: magrittr
set.seed(7337)

## Create arbitrary tibble
myTibble <- tibble(x = 1:10,
                   y = runif(10),
                   z = y * pi)

## I can mutate across these columns
mutate(myTibble, across(everything(), multiply_by, 2))
#> # A tibble: 10 x 3
#>        x       y      z
#>    <dbl>   <dbl>  <dbl>
#>  1     2 1.78    5.58  
#>  2     4 0.658   2.07  
#>  3     6 0.105   0.331 
#>  4     8 1.75    5.50  
#>  5    10 1.33    4.19  
#>  6    12 1.02    3.20  
#>  7    14 1.20    3.75  
#>  8    16 0.00794 0.0250
#>  9    18 0.108   0.340 
#> 10    20 1.74    5.45

## I can subsequently rename these columns
mutate(myTibble, across(everything(), multiply_by, 2)) %>% 
  rename_with(paste0, everything(), "_double")
#> # A tibble: 10 x 3
#>    x_double y_double z_double
#>       <dbl>    <dbl>    <dbl>
#>  1        2  1.78      5.58  
#>  2        4  0.658     2.07  
#>  3        6  0.105     0.331 
#>  4        8  1.75      5.50  
#>  5       10  1.33      4.19  
#>  6       12  1.02      3.20  
#>  7       14  1.20      3.75  
#>  8       16  0.00794   0.0250
#>  9       18  0.108     0.340 
#> 10       20  1.74      5.45

## But how can I achieve this (without the fuss of creating & joining an additional table):

# A tibble: 10 x 6
    # x      y     z           x_double y_double z_double
# <int>  <dbl> <dbl>        <dbl>    <dbl>    <dbl>
#   1     1 0.313  0.982      2    0.625    1.96 
  # 2     2 0.759  2.39       4    1.52     4.77 
  # 3     3 0.705  2.22       6    1.41     4.43 
  # 4     4 0.573  1.80       8    1.15     3.60 
  # 5     5 0.599  1.88      10    1.20     3.77 
  # 6     6 0.0548 0.172     12    0.110    0.344
  # 7     7 0.571  1.80      14    1.14     3.59 
  # 8     8 0.621  1.95      16    1.24     3.90 
  # 9     9 0.709  2.23      18    1.42     4.46 
  # 10    10 0.954  3.00     20    1.91     5.99 

reprex 包于 2021-09-16 创建(v2.0.1)

标签: rrenamedplyracross

解决方案


使用的.names论点across

across使用参数命名它的输出,参数.names是传递给glue::glue(). 这是一个字符串,其中"{.col}""{.fn}"被您的列(由 指定.cols)和函数(由指定.fns)的名称替换

的默认值为.namesNULL,相当于"{.col}". 这意味着每个变异的列都被分配了与其对应的相同名称 in .cols,这有效地“覆盖”了输出中的这些列。

要生成所需的表格,您需要执行以下操作:

require(dplyr)
#> Loading required package: dplyr
#> 
#> Attaching package: 'dplyr'
#> The following objects are masked from 'package:stats':
#> 
#>     filter, lag
#> The following objects are masked from 'package:base':
#> 
#>     intersect, setdiff, setequal, union
require(magrittr)
#> Loading required package: magrittr
set.seed(7337)

## Create arbitrary tibble
myTibble <- tibble(x = 1:10,
                   y = runif(10),
                   z = y * pi)

mutate(myTibble, across(everything(), multiply_by, 2, .names = "{.col}_double"))
#> # A tibble: 10 x 6
#>        x       y      z x_double y_double z_double
#>    <int>   <dbl>  <dbl>    <dbl>    <dbl>    <dbl>
#>  1     1 0.889   2.79          2  1.78      5.58  
#>  2     2 0.329   1.03          4  0.658     2.07  
#>  3     3 0.0527  0.165         6  0.105     0.331 
#>  4     4 0.875   2.75          8  1.75      5.50  
#>  5     5 0.666   2.09         10  1.33      4.19  
#>  6     6 0.509   1.60         12  1.02      3.20  
#>  7     7 0.598   1.88         14  1.20      3.75  
#>  8     8 0.00397 0.0125       16  0.00794   0.0250
#>  9     9 0.0541  0.170        18  0.108     0.340 
#> 10    10 0.868   2.73         20  1.74      5.45

reprex 包于 2021-09-16 创建(v2.0.1)

这样,你可以使用acrosswith.fns.namesto 做很多事情:

mutate(myTibble, across(everything(),
                        .fns = list(double = multiply_by, half = divide_by),
                        2,
                        .names = "{.col}_{.fn}"))
#> # A tibble: 10 x 9
#>        x       y      z x_double x_half y_double  y_half z_double  z_half
#>    <int>   <dbl>  <dbl>    <dbl>  <dbl>    <dbl>   <dbl>    <dbl>   <dbl>
#>  1     1 0.889   2.79          2    0.5  1.78    0.444     5.58   1.40   
#>  2     2 0.329   1.03          4    1    0.658   0.165     2.07   0.517  
#>  3     3 0.0527  0.165         6    1.5  0.105   0.0263    0.331  0.0827 
#>  4     4 0.875   2.75          8    2    1.75    0.437     5.50   1.37   
#>  5     5 0.666   2.09         10    2.5  1.33    0.333     4.19   1.05   
#>  6     6 0.509   1.60         12    3    1.02    0.255     3.20   0.800  
#>  7     7 0.598   1.88         14    3.5  1.20    0.299     3.75   0.939  
#>  8     8 0.00397 0.0125       16    4    0.00794 0.00199   0.0250 0.00624
#>  9     9 0.0541  0.170        18    4.5  0.108   0.0271    0.340  0.0850 
#> 10    10 0.868   2.73         20    5    1.74    0.434     5.45   1.36

推荐阅读