Reputation: 432
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:
Upvotes: 0
Views: 1192
Reputation: 47320
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
#
Upvotes: 1
Reputation: 13125
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)
Upvotes: 1
Reputation: 60080
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
})
Upvotes: 1