Issue converting multiple column classes in R data.table

Viewed 59

I would like to convert a list of variables in R data.table, however, this conversion lead to unexpected consequence. I'm running under R version 4.0.1 with library data.table_1.12.8. Here is a simplified example:

> dput(norw5)
structure(list(Born_before_2016 = c(1L, 1L, 1L, 1L, 1L), gender = c("2.Female", 
"1.Male", "2.Female", "1.Male", "1.Male"), payor = c("1:Private", 
"1:Private", "4:Other", "4:Other", "1:Private"), Age_in_day = c(0L, 
0L, 0L, 4L, 5L)), row.names = c(NA, -5L), class = c("data.table", 
"data.frame"), .internal.selfref = <pointer: 0x0000024ce5a41ef0>)
library(data.table)

fact <- c('Born_before_2016', 'gender', 'payor')

varls <- scan(text=fact, what = "", quiet = T)

factcols <- sapply(norw5[,..varls], is.numeric)

norw5new <- norw5[, names(norw5)[factcols] := lapply(.SD, as.character),
                  .SDcols = factcols]
> dput(norw5new)
structure(list(Born_before_2016 = c("1", "1", "1", "1", "1"), 
    gender = c("2.Female", "1.Male", "2.Female", "1.Male", "1.Male"
    ), payor = c("1:Private", "1:Private", "4:Other", "4:Other", 
    "1:Private"), Age_in_day = c("0", "0", "0", "4", "5")), row.names = c(NA, 
-5L), class = c("data.table", "data.frame"), .internal.selfref = <pointer: 0x0000024ce5a41ef0>)

As you shown above, finding numeric variables (Born_before_2016 in this example) and converting them to character is the goal. However, conversion is expanded to additional variable Age_in_day, which is not in the list at all. I couldn't figure this out, can R gurus here point me a right direction of fixing this? Thanks!

1 Answers

factcols in .SDcols=factcols should be a length-4 logical vector or the vector of column name/position, e.g. .SDcols = c("Born_before_2016"),.SDcols = 1, but factcols <- sapply(norw5[,..varls], is.numeric) returns length-3 logical vector. It can be fixed as

fact <- c('Born_before_2016','gender','payor')
factcols <- sapply(norw5[,..fact], is.numeric)
cols <- names(norw5)[1:3][factcols]
norw5new <- norw5[,(cols) := lapply(.SD,as.character),.SDcols=cols]
norw5new 

#   Born_before_2016   gender     payor Age_in_day
#             <char>   <char>    <char>      <int>
#1:                1 2.Female 1:Private          0
#2:                1   1.Male 1:Private          0
#3:                1 2.Female   4:Other          0
#4:                1   1.Male   4:Other          4
#5:                1   1.Male 1:Private          5
Related