Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Rename multiple dataframe columns using purrr

Tags:

r

purrr

tidyverse

I have the following list of data frames containing a column named cyl

# Create 3 dataframes with identical column names
mt_list <- list(head(mtcars[, 1:2]), tail(mtcars[, 1:2]), mtcars[13:18, 1:2])
mt_list
#> [[1]]
#>                    mpg cyl
#> Mazda RX4         21.0   6
#> Mazda RX4 Wag     21.0   6
#> Datsun 710        22.8   4
#> Hornet 4 Drive    21.4   6
#> Hornet Sportabout 18.7   8
#> Valiant           18.1   6
#> 
#> [[2]]
#>                 mpg cyl
#> Porsche 914-2  26.0   4
#> Lotus Europa   30.4   4
#> Ford Pantera L 15.8   8
#> Ferrari Dino   19.7   6
#> Maserati Bora  15.0   8
#> Volvo 142E     21.4   4
#> 
#> [[3]]
#>                      mpg cyl
#> Merc 450SL          17.3   8
#> Merc 450SLC         15.2   8
#> Cadillac Fleetwood  10.4   8
#> Lincoln Continental 10.4   8
#> Chrysler Imperial   14.7   8
#> Fiat 128            32.4   4

# New 'cyl' column names to change to (they are a character vector)
new_cyl_names <- c("cyl1", "cyl2", "cyl3")
new_cyl_names
#> [1] "cyl1" "cyl2" "cyl3"

I would like to name cyl to be the corresponding value in the character vector new_cyl_names.

I tried to do this as follows:

# Custom function to change cyl to the 
# character value contained in new_colname
change_colname_cyl <- function(df, new_colname){
    df %>% 
        dplyr::rename(new_colname = cyl)
}

# The following should change the names to cyl1, cyl2, cyl3
purrr::map2(.x = mt_list, .y = new_cyl_names, ~ change_colname_cyl(.x, .y))

This results in (first data frame shown only):

[[1]]
                   mpg new_colname
Mazda RX4         21.0           6
Mazda RX4 Wag     21.0           6
Datsun 710        22.8           4
Hornet 4 Drive    21.4           6
Hornet Sportabout 18.7           8
Valiant           18.1           6

Could anyone please help me use purrr correctly for this i.e. change cyl to cyl1 in this case instead of new_colname per above?

like image 375
user4687531 Avatar asked Oct 07 '17 04:10

user4687531


2 Answers

I made a slight modification of your function. I think now it works. See this (https://cran.r-project.org/web/packages/dplyr/vignettes/programming.html) to learn more about standard evaluation and non-standard evaluation in dplyr.

library(tidyverse)

# List of data frames
mt_list <- list(head(mtcars[, 1:2]), tail(mtcars[, 1:2]), mtcars[13:18, 1:2])

# New column names
new_cyl_names <- c("cyl1", "cyl2", "cyl3")

# Create the function
change_colname_cyl <- function(df, new_colname){
  df %>% rename(!!new_colname := cyl)
}

# Apply the function
map2(mt_list, new_cyl_names, ~ change_colname_cyl(.x, .y))
[[1]]
                   mpg cyl1
Mazda RX4         21.0    6
Mazda RX4 Wag     21.0    6
Datsun 710        22.8    4
Hornet 4 Drive    21.4    6
Hornet Sportabout 18.7    8
Valiant           18.1    6

[[2]]
                mpg cyl2
Porsche 914-2  26.0    4
Lotus Europa   30.4    4
Ford Pantera L 15.8    8
Ferrari Dino   19.7    6
Maserati Bora  15.0    8
Volvo 142E     21.4    4

[[3]]
                     mpg cyl3
Merc 450SL          17.3    8
Merc 450SLC         15.2    8
Cadillac Fleetwood  10.4    8
Lincoln Continental 10.4    8
Chrysler Imperial   14.7    8
Fiat 128            32.4    4

Update

Based on Paul's comments. The following seems to be a more direct and concise way to rename the column.

map2(mt_list, new_cyl_names, ~rename(.x, !!.y := cyl))
like image 125
www Avatar answered Oct 01 '22 12:10

www


We could use the setnames from data.table

library(data.table)
library(tidyverse)
map2(mt_list, new_cyl_names, ~setnames(.x, 'cyl', .y))
mt_list
#[[1]]
#                   mpg cyl1
#Mazda RX4         21.0    6
#Mazda RX4 Wag     21.0    6
#Datsun 710        22.8    4
#Hornet 4 Drive    21.4    6
#Hornet Sportabout 18.7    8
#Valiant           18.1    6

#[[2]]
#                mpg cyl2
#Porsche 914-2  26.0    4
#Lotus Europa   30.4    4
#Ford Pantera L 15.8    8
#Ferrari Dino   19.7    6
#Maserati Bora  15.0    8
#Volvo 142E     21.4    4

#[[3]]
#                     mpg cyl3
#Merc 450SL          17.3    8
#Merc 450SLC         15.2    8
#Cadillac Fleetwood  10.4    8
#Lincoln Continental 10.4    8
#Chrysler Imperial   14.7    8
#Fiat 128            32.4    4
like image 25
akrun Avatar answered Oct 01 '22 12:10

akrun