How to convert entire dataframe to numeric while preserving decimals?

151,104

Solution 1

You might need to do some checking. You cannot safely convert factors directly to numeric. as.character must be applied first. Otherwise, the factors will be converted to their numeric storage values. I would check each column with is.factor then coerce to numeric as necessary.

df1[] <- lapply(df1, function(x) {
    if(is.factor(x)) as.numeric(as.character(x)) else x
})
sapply(df1, class)
#         a         b 
# "numeric" "numeric" 

Solution 2

Using dplyr (a bit like sapply..)

df2 <- mutate_all(df1, function(x) as.numeric(as.character(x)))

which gives:

glimpse(df2)
Observations: 4
Variables: 2
$ a <dbl> 0.01, 0.02, 0.03, 0.04
$ b <dbl> 2, 4, 5, 7

from your df1 which was:

glimpse(df1)
Observations: 4
Variables: 2
$ a <fctr> 0.01, 0.02, 0.03, 0.04
$ b <dbl> 2, 4, 5, 7

Solution 3

df2 <- data.frame(apply(df1, 2, function(x) as.numeric(as.character(x))))

Solution 4

> df2 <- data.frame(sapply(df1, function(x) as.numeric(as.character(x))))
> df2
     a b
1 0.01 2
2 0.02 4
3 0.03 5
4 0.04 7
> sapply(df2, class)
        a         b 
"numeric" "numeric" 
Share:
151,104
Borealis
Author by

Borealis

Updated on November 03, 2020

Comments

  • Borealis
    Borealis over 3 years

    I have a mixed class dataframe (numeric and factor) where I am trying to convert the entire data frame to numeric. The following illustrates the type of data I am working with as well as the problem I am encountering:

    > a = as.factor(c(0.01,0.02,0.03,0.04))
    > b = c(2,4,5,7)
    > df1 = data.frame(a,b)
    > class(df1$a)
    [1] "factor"
    > class(df1$b)
    [1] "numeric"
    

    When I try and convert the entire data frame to numeric, it alters the numeric values. For example:

    > df2 = as.data.frame(sapply(df1, as.numeric))
    > class(df2$a)
    [1] "numeric"
    > df2
      a b
    1 1 2
    2 2 4
    3 3 5
    4 4 7
    

    Previous posts on this site suggest using as.numeric(as.character(df1$a)), which works great for one column. However, I need to apply this approach to a dataframe that may contain hundreds of columns.

    What are my options for converting an entire dataframe from factor to numeric, while preserving the numeric decimal values?

    The following is the output I would like to produce where a and b are numeric:

         a b
    1 0.01 2
    2 0.02 4
    3 0.03 5
    4 0.04 7
    

    I have read the following related posts, although none of them apply directly to this case:

    1. How to convert a factor variable to numeric while preserving the numbers in R This references a single column in a dataframe.
    2. converting from a character to a numeric data frame. This post does not take into account decimal values.
    3. How can i convert a factor column that contains decimal numbers to numeric?. This applies to only one column in a data frame.
  • Rich Scriven
    Rich Scriven over 9 years
    I could be wrong, but won't this convert a numeric column to character then back to numeric again?
  • n8sty
    n8sty over 9 years
    @RichardScriven think that's right. I think my answer suffers from the same issue, though I don't think it's particularly problematic.
  • Rich Scriven
    Rich Scriven over 9 years
    @n8sty No, it's not problematic at all, but it seems a bit wasteful.
  • hadley
    hadley over 9 years
    Or do it outside the loop: is_factor <- vapply(df1, is.factor, logical(1)); df1[is_factor] <- ...
  • Rich Scriven
    Rich Scriven over 9 years
    @hadley - I've been wondering about this. It is more efficient to check first, and then run the change on the subset? Rather than checking inside the lapply loop?
  • hadley
    hadley over 9 years
    Given the size of typical dataset I doubt it would make much difference