Rename the last n columns

Is it possible to solve this issue with base and tidyverse (preferable) tools?

library(tidyverse)

# I have
tibble(a = 1, b = 2, c = 3)
#> # A tibble: 1 x 3
#>       a     b     c
#>   <dbl> <dbl> <dbl>
#> 1     1     2     3

# here we apply something like
tbl %>% desired_rename_function(last(names(.), 2), c("second", "third"))

# I want
tibble(a = 1, second = 2, third = 3)
#> # A tibble: 1 x 3
#>       a second third
#>   <dbl>  <dbl> <dbl>
#> 1     1      2     3

Created on 2018-09-11 by the reprex package (v0.2.0).

rename_at() has .vars argument. I believe it could solve the problem if the argument for new names accepted a vector, not a list of functions. rename() is not flexible as far as I can see, it forces you to specify the exact pairs of column names

There is one way to do it:

library(tidyverse)

test <- tibble(a = 1, b = 2, c = 3)

desired_rename_function <- function(df, n_last, vec2){
  nms <- names(df) %>% `[`(seq(from = ncol(df) - n_last + 1, to = ncol(df)))
  vec <- setNames(object = nms, vec2)
  df %>%
    dplyr::rename(
      !!!vec
    )
}

test %>% desired_rename_function(n_last = 2, c("second", "third"))
#> # A tibble: 1 x 3
#>       a second third
#>   <dbl>  <dbl> <dbl>
#> 1     1      2     3

Created on 2018-09-11 by the reprex package (v0.2.0).

Of course, you'll need to take care not to call it with congruent numbers between n_last and length of the vector with new names.

1 Like

Did this quick.

library(tidyverse)
tbl <- tibble(a = 1, b = 2, c = 3, d = 4, e = 5, f = 6)

desired_rename_function <- function(x, y, z) {
  x %>% 
    rename_at(
      vars(
        names(.) %>%
          tail(y)),
      funs(paste(z))
    )
}

desired_rename_function(tbl, y = 2, z = c("hello", "yes"))
#> # A tibble: 1 x 6
#>       a     b     c     d hello   yes
#>   <dbl> <dbl> <dbl> <dbl> <dbl> <dbl>
#> 1     1     2     3     4     5     6

tbl %>% desired_rename_function(., y = 2, z = c("hello", "yes"))
#> # A tibble: 1 x 6
#>       a     b     c     d hello   yes
#>   <dbl> <dbl> <dbl> <dbl> <dbl> <dbl>
#> 1     1     2     3     4     5     6

Created on 2018-09-11 by the reprex package (v0.2.0).

2 Likes

Thanks for reminding that tail exists :slight_smile:

It makes my approach much more legible:

library(tidyverse)

test <- tibble(a = 1, b = 2, c = 3)

desired_rename_function <- function(df, n_last, vec2){
  nms <- tail(names(df), n_last)
  vec <- setNames(object = nms, vec2)
  
  df %>%
    dplyr::rename(
      !!!vec
    )
}

test %>% desired_rename_function(n_last = 2, c("second", "third"))
#> # A tibble: 1 x 3
#>       a second third
#>   <dbl>  <dbl> <dbl>
#> 1     1      2     3

Created on 2018-09-11 by the reprex package (v0.2.0).

1 Like

@nviau solution (more tidyverse) in other words

library(tidyverse)
n <- 2
tibble(a = 1, b = 2, c = 3) %>% 
    rename_at(vars(tail(names(.), n)), funs(c("second", "third")))
#> # A tibble: 1 x 3
#>       a second third
#>   <dbl>  <dbl> <dbl>
#> 1     1      2     3

Created on 2018-09-11 by the reprex package (v0.2.0).

1 Like