0
votes

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:

3

3 Answers

1
votes
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)
1
votes

The function you're mapping is returning the column names, you need it to return the actual tibble instead:

all_tbls %<>% map(function(tbl) { 
    colnames(tbl) %<>% map(tolower)
    tbl
})
1
votes

You can use purrr::map and dplyr::rename_all :

all_tbls <- list(head(iris,2), head(cars,2))

library(tidyverse)
all_tbls %>% map(rename_all, toupper)
# [[1]]
#   SEPAL.LENGTH SEPAL.WIDTH PETAL.LENGTH PETAL.WIDTH SPECIES
# 1          5.1         3.5          1.4         0.2  setosa
# 2          4.9         3.0          1.4         0.2  setosa
# 
# [[2]]
#   SPEED DIST
# 1     4    2
# 2     4   10
#