userJT
userJT

Reputation: 11934

Convert all columns to characters in a data.frame

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.

Upvotes: 59

Views: 92230

Answers (6)

Jake Thompson
Jake Thompson

Reputation: 2843

EDIT: 2021-03-01

Beginning with dplyr 1.0.0, the _all() function variants are deprecated. 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)

Upvotes: 103

Quinten
Quinten

Reputation: 41225

Another option could be using the map_df function from the purrr package like this:

library(purrr)
map_df(mtcars, as.character)
#> # A tibble: 32 × 11
#>    mpg   cyl   disp  hp    drat  wt    qsec  vs    am    gear  carb 
#>    <chr> <chr> <chr> <chr> <chr> <chr> <chr> <chr> <chr> <chr> <chr>
#>  1 21    6     160   110   3.9   2.62  16.46 0     1     4     4    
#>  2 21    6     160   110   3.9   2.875 17.02 0     1     4     4    
#>  3 22.8  4     108   93    3.85  2.32  18.61 1     1     4     1    
#>  4 21.4  6     258   110   3.08  3.215 19.44 1     0     3     1    
#>  5 18.7  8     360   175   3.15  3.44  17.02 0     0     3     2    
#>  6 18.1  6     225   105   2.76  3.46  20.22 1     0     3     1    
#>  7 14.3  8     360   245   3.21  3.57  15.84 0     0     3     4    
#>  8 24.4  4     146.7 62    3.69  3.19  20    1     0     4     2    
#>  9 22.8  4     140.8 95    3.92  3.15  22.9  1     0     4     2    
#> 10 19.2  6     167.6 123   3.92  3.44  18.3  1     0     4     4    
#> # … with 22 more rows

Created on 2023-04-02 with reprex v2.0.2

If you want to have the output to be a data.frame, you could add as.data.frame to your pipe.

Upvotes: 2

Sam Firke
Sam Firke

Reputation: 23014

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)

Upvotes: 39

HBat
HBat

Reputation: 5682

mutate_all in the accepted answer is superseded.

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

library(dplyr)

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

Upvotes: 2

Rushabh Patel
Rushabh Patel

Reputation: 2764

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")))

Upvotes: 5

Sean Lin
Sean Lin

Reputation: 815

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

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

Upvotes: 4

Related Questions