Reputation: 11934
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
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
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
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
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
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
Reputation: 815
This might work, but not sure if it's the best.
df = data.frame(lapply(mtcars, as.character))
str(df)
Upvotes: 4