Convert all columns to characters in a data.frame

53,118

Solution 1

EDIT: 2021-03-01

Beginning with dplyr 1.0.0, the _all() function variants are superceded. The new way to accomplish this is using the new across() function.

library(dplyr)
mtcars %>%
  mutate(across(everything(), as.character))

With across(), we choose the set of columns we want to modify using tidyselect helpers (here we use everything() to choose all columns), and then specify the function we want to apply to each of the selected columns. In this case, that is as.character().

Original answer:

You can also use dplyr::mutate_all.

library(dplyr)
mtcars %>%
  mutate_all(as.character)

Solution 2

In base R:

x[] <- lapply(x, as.character)

This converts the columns to character class in place, retaining the data.frame's attributes. A call to data.frame() would cause them to be lost.

Attribute preservation using dplyr: Attributes seem to be preserved during dplyr::mutate(across(everything(), as.character)). Previously they were destroyed by dplyr::mutate_all.

Example

x <- mtcars
attr(x, "example") <- "1"

In the second case below, the example attribute is retained:

# Destroys attributes

data.frame(lapply(x, as.character)) %>%
  attributes()

# Preserves attributes

x[] <- lapply(x, as.character)
attributes(x)

Solution 3

This might work, but not sure if it's the best.

df = data.frame(lapply(mtcars, as.character))
str(df)

Solution 4

Most efficient way using data.table-

data.table::setDT(mtcars)
mtcars[, (colnames(mtcars)) := lapply(.SD, as.character), .SDcols = colnames(mtcars)]

Note: You can use this to convert few columns of a data table to your desired column type.

If we want to convert all columns to character then we can also do something like this-

to_col_type <- function(col_names,type){
            get(paste0("as.", type))(dt[[col_names]])
            }
mtcars<- rbindlist(list(Map(to_col_type ,colnames(mtcars),"character")))

Solution 5

mutate_all in the accepted answer is superseded.

You can use mutate() function with across():

library(dplyr)

mtcars %>% 
  mutate(across(everything(), as.character))
Share:
53,118
userJT
Author by

userJT

user of SE

Updated on July 09, 2022

Comments

  • userJT
    userJT almost 2 years

    Consider a data.frame with a mix of data types.

    For a weird purpose, a user needs to convert all columns to characters. How is it best done? A tidyverse attempt at solution is this:

    map(mtcars,as.character) %>% map_df(as.list) %>% View()
    c2<-map(mtcars,as.character) %>% map_df(as.list)
    

    when I call str(c2) it should say a tibble or data.frame with all characters.

    The other option would be some parameter settings for write.csv() or in write_csv() to achieve the same thing in the resulting file output.

  • sindri_baldur
    sindri_baldur almost 6 years
    I think this can be simplified to x[] <- lapply(x, as.character)
  • stevec
    stevec almost 5 years
    This is the best answer IMO, on the basis that it preserves attributes of the data.frame. @Sam is there any reason not to simply as sindri suggests?
  • Sam Firke
    Sam Firke over 3 years
    good call, I have updated the answer with this simpler command
  • vasili111
    vasili111 over 3 years
    @sindri_baldur Could you please clarify how x[] <- lapply(x, as.character) works? I mean, lapply accepts list and returns list. How here lapply is working with data frame?
  • sindri_baldur
    sindri_baldur over 3 years
    @vasili111 Adding [] forces it to not lose its attributes (data.frame in this case (which is built on a special type of lists)).
  • vasili111
    vasili111 over 3 years
    @sindri_baldur Thank you.
  • Henrik
    Henrik about 3 years
  • Jake Thompson
    Jake Thompson about 3 years
    Thanks! I've updated my answer to reflect the updated dplyr syntax.