Search code examples
loopsdictionarydplyrrenamenest

Best way to rename multiple columns after using nest() and map() in R


I wanted to know what is the best way to rename multiple columns after using nest() and map().

I have a sample code of what I have done at the moment to achieve this using the iris dataset.


iris_names <- colnames(iris[, 1:4])

iris_sqrt <- iris %>% 
  nest(-Species) %>% 
  mutate(square_root = map(data, sqrt)) %>% 
  unnest(square_root)

names(iris_sqrt)[3:ncol(iris_sqrt)] <- paste0(iris_names, ".sd")

Here, I make a vector of the column names I want to rename before creating iris_sqrt and then renaming using paste0. The drawback of this method is the column name has to appear in the same order as the iris_names vector to rename correctly.

Is there a tidyverse/dplyr way of doing this?


Solution

  • You can use mutate inside the map call. Use across on everything, apply sqrt, using the .names argument you can change the names of the new columns, and use .keep = "unused" in mutate to remove the columns that were used during the calculation:

    iris %>% 
      nest(data = -Species) %>% 
      mutate(square_root = map(data, ~ .x %>% 
                                 mutate(across(everything(), sqrt, 
                                               .names = "{.col}.sd"),
                                               .keep = "unused"))) %>% 
      unnest(square_root)
    

    output

    # A tibble: 150 × 6
       Species data              Sepal.Length.sd Sepal.Width.sd Petal.Length.sd Petal.Width.sd
       <fct>   <list>                      <dbl>          <dbl>           <dbl>          <dbl>
     1 setosa  <tibble [50 × 4]>            2.26           1.87            1.18          0.447
     2 setosa  <tibble [50 × 4]>            2.21           1.73            1.18          0.447
     3 setosa  <tibble [50 × 4]>            2.17           1.79            1.14          0.447
     4 setosa  <tibble [50 × 4]>            2.14           1.76            1.22          0.447
     5 setosa  <tibble [50 × 4]>            2.24           1.90            1.18          0.447
     6 setosa  <tibble [50 × 4]>            2.32           1.97            1.30          0.632
     7 setosa  <tibble [50 × 4]>            2.14           1.84            1.18          0.548
     8 setosa  <tibble [50 × 4]>            2.24           1.84            1.22          0.447
     9 setosa  <tibble [50 × 4]>            2.10           1.70            1.18          0.447
    10 setosa  <tibble [50 × 4]>            2.21           1.76            1.22          0.316
    # … with 140 more rows
    # ℹ Use `print(n = ...)` to see more rows