Search code examples
rpurrrmagrittr

Mapping the same function to multiple tibbles in a list


I have several tibbles, each of which has different numbers of columns and different column names. I want to standardize the column names for each to be all lowercase. This works for an individual tibble:

library(magrittr)
library(purrr)

colnames(tbl1) %<>% map(tolower)

The column names for the object tbl1 are now all lowercase.

If I put all my tibbles in a list, however, this doesn't work:

all_tbls <- list(tbl1, tbl2, tbl3)
all_tbls %<>% map(function(tbl) {colnames(tbl) %<>% map(tolower)})

The colnames for the objects tbl1, tbl2, and tbl3 are not changed by this. The objects in the list all_tbls are now lists of the column names for each tbl, i.e. what you'd get if you applied as.list() to the result of colnames()).

Why is this happening? Is there a better approach to doing this? I'd prefer to use tidyverse functions (e.g. map instead of *apply) for consistency with other code, but am open to other solutions. EDIT: To be clear, I'd like to be able to work with the original tibble objects, i.e. the desired outcome is for the colnames of tbl1, tbl2, and tbl3 to change.

Other Q&A I looked at and did not find illuminating includes:


Solution

  • library(magrittr)
    library(purrr)
    all_tbls %<>% map(~set_names(.x,tolower(colnames(.x))))
    

    The objects in the list all_tbls are now lists of the column names for each tbl

    Because you're asking map to lower the column names and return them as a list

    To modify in place we can use data.table::setnames, since data.table using copy in place against copy by reference.

    library(data.table)
    library(purrr)
    map(list(df1,df2),~setnames(.,old = names(.), new = tolower(names(.))))
    

    Data

    df1 <- read.table(text='
    A B
    1 1',header=TRUE)
    
    df2 <- read.table(text='
    C D
    2 2',header=TRUE)