Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why does R convert numbers and characters to factors when coercing to data frame?

Tags:

r

Recently I have come across a problem where my data has been converted to factors. This is a large nuisance, as it's not (always) easily picked up on.

I am aware that I can convert them back with solutions such as as.character(paste(x)) or as.character(paste(x)), but that seems really unnecessary.

Example code:

nums <- c(1,2,3,4,5)
chars <- c("A","B","C,","D","E")
str(nums)
#>  num [1:5] 1 2 3 4 5
str(chars)
#>  chr [1:5] "A" "B" "C," "D" "E"
df <- as.data.frame(cbind(a = nums, b = chars))
str(df)
#> 'data.frame':    5 obs. of  2 variables:
#>  $ a: Factor w/ 5 levels "1","2","3","4",..: 1 2 3 4 5
#>  $ b: Factor w/ 5 levels "A","B","C,","D",..: 1 2 3 4 5
like image 236
mhovd Avatar asked Jan 24 '26 15:01

mhovd


2 Answers

  1. Don't cbind as it converts data to matrix and matrix can hold data of only one type, so it converts numbers to characters.

  2. Use data.frame because as.data.frame(a = nums, b = chars) returns an error.

  3. Use stringsAsFactors = FALSE because in data.frame default value of stringsAsFactors is TRUE which converts characters to factors. The numbers also change to factors because in 1) they have been changed to characters.

    df <- data.frame(a = nums, b = chars, stringsAsFactors = FALSE)
     str(df)
     #'data.frame':  5 obs. of  2 variables:
     # $ a: num  1 2 3 4 5
     # $ b: chr  "A" "B" "C," "D" ...
    

EDIT: As of the newest version of R, the default value of stringAsFactors has changed to FALSE.

like image 138
Ronak Shah Avatar answered Jan 26 '26 07:01

Ronak Shah


This should no longer happen if you have updated R: data frames don't automatically turn chr to fct. In a way, data frames are now more similar to tibbles.

like image 21
Guilherme D. Garcia Avatar answered Jan 26 '26 09:01

Guilherme D. Garcia



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!