0

I am looking to convert the columns of a datatable into another class and I am stuck with the inability to refer to the columns using strings.

set.seed(10238)
idt <- data.table(A = rep(1:3, each = 5), B = rep(1:5, 3),
                 C = sample(15), D = sample(15)) 

> idt
    A B  C  D
 1: 1 1 10 14
 2: 1 2  2  2
 3: 1 3 13  3
 4: 1 4  7  1
 5: 1 5  1  8
 6: 2 1 11 15
 7: 2 2  4 10
 8: 2 3 15  7
 9: 2 4 14 12
10: 2 5  5  9
11: 3 1  8 13
12: 3 2  3  4
13: 3 3  9  6
14: 3 4  6 11
15: 3 5 12  5

#All columns are integers 
    > lapply(idt, class)
$A
[1] "integer"
$B
[1] "integer"
$C
[1] "integer"
$D
[1] "integer"

vec = parse(text=c('A','B','C','D'))
for (i in vec) idt[, eval( i ) := as.character( eval(i) ) ]
Error in eval(expr, envir, enclos) : object 'A' not found*

I want to reassign the columns classes by looping through a vector containing the strings representing the names of the columns I want to convert.

I am aware of other threads adressing the same problem but they are not very understandable. My question is why can't I loop through expressions and eval them just like I would do manually replacing the the i in the j-expressions with the column names for each column.

** EDIT NOT A DUPLICATE **

I am aware of other threads adressing the same problem but they are not very understandable. My question is why can't I loop through expressions and eval them just like I would do manually replacing the the i in the j-expressions with the column names for each column.

Community
  • 1
  • 1
ChiseledAbs
  • 1,963
  • 6
  • 19
  • 33
  • I guess you need `for(i in vec) idt[, (i) := as.character(get(i))]` where `vec <- names(idt)` – akrun Feb 08 '17 at 14:57
  • 3
    voting to close because [this answer](http://stackoverflow.com/a/32942319/2761575) works perfectly for you and is basically reproduced in the answers below – dww Feb 08 '17 at 15:03

2 Answers2

13

We can do this with a for loop by looping over the column names of 'idt'. In this case we get the values of the string, convert it to character and assign (:=) it to the string name or column name ((i))

vec <- names(idt)
for(i in vec) idt[, (i) := as.character(get(i))]

Or using .SDcols, we specify the columns of interest in .SDcols, loop through the Subset of data.table (.SD) with lapply and assign (:=) it to the vector of column names ('vec')

id1[, (vec) := lapply(.SD, as.character), .SDcols = vec]
akrun
  • 874,273
  • 37
  • 540
  • 662
2

Try this:

names <- colnames(idt)
idt <- idt[, lapply(.SD, as.character), .SDcols = (names)]

.SD can be used with data.table to get a subset of the data. .SDcols is used to tell data.table which columns to lapply the function to.


Based on this answer, the following is a better approach:

names <- colnames(idt)
idt[, (names) := lapply(.SD, as.character), .SDcols = names]
Community
  • 1
  • 1
GarAust89
  • 347
  • 1
  • 10
  • Please see [my answer](http://stackoverflow.com/a/32942319/2204410) in the linked question above. This is not the way it should be done with `data.table`. – Jaap Feb 08 '17 at 16:55
  • Thanks for the feedback Jaap. I've updated my answer to reflect your own. – GarAust89 Feb 08 '17 at 17:34