An Elegant way to change columns type in dataframe in R

It's tasks like this that I think are best accomplished with explicit loops. You don't buy anything here by replacing a straightforward for-loop with the hidden loop of a function like lapply(). Example:

## generate data
set.seed(1L);
N <- 3L; test.data <- data.frame(age=sample(20:90,N,T),gender=factor(sample(c('M','F'),N,T)),work.years=sample(1:5,N,T),name=sample(letters,N,T),stringsAsFactors=F);
test.data;
##   age gender work.years name
## 1  38      F          5    b
## 2  46      M          4    f
## 3  60      F          4    e
str(test.data);
## 'data.frame':   3 obs. of  4 variables:
##  $ age       : int  38 46 60
##  $ gender    : Factor w/ 2 levels "F","M": 1 2 1
##  $ work.years: int  5 4 4
##  $ name      : chr  "b" "f" "e"

## solution
for (cn in names(test.data)[sapply(test.data,is.integer)])
    test.data[[cn]] <- as.double(test.data[[cn]]);

## result
test.data;
##   age gender work.years name
## 1  38      F          5    b
## 2  46      M          4    f
## 3  60      F          4    e
str(test.data);
## 'data.frame':   3 obs. of  4 variables:
##  $ age       : num  38 46 60
##  $ gender    : Factor w/ 2 levels "F","M": 1 2 1
##  $ work.years: num  5 4 4
##  $ name      : chr  "b" "f" "e"

Now very elegant in dplyr (with magrittr %<>% operator)

test.data %<>% mutate_if(is.integer,as.numeric)

I think elegant code is sometimes subjective. For me, this is elegant but it may be less efficient compared to the OP's code. However, as the question is about elegant code, this can be used.

test.data[] <- lapply(test.data, function(x) if(is.integer(x)) as.numeric(x) else x)

Also, another elegant option is dplyr

library(dplyr)
library(magrittr)
test.data %<>% 
      mutate_each(funs(if(is.integer(.)) as.numeric(.) else .))

Tags:

R