I must admit that the data.table J syntax confuses me.
I am attempting to use list() to extract a subset of a data.table as a data.table object as described in Section 1.4 of the data.table FAQ, but I can't get this behavior to work inside of a function.
An example:
require(data.table)
## Setup some test data
set.seed(1)
test.data <- data.table( X = rnorm(10),
Y = rnorm(10),
Z = rnorm(10) )
setkey(test.data, X)
## Notice that I can subset the data table easily with literal names
test.data[, list(X,Y)]
## X Y
## 1: -0.8356286 -0.62124058
## 2: -0.8204684 -0.04493361
## 3: -0.6264538 1.51178117
## 4: -0.3053884 0.59390132
## 5: 0.1836433 0.38984324
## 6: 0.3295078 1.12493092
## 7: 0.4874291 -0.01619026
## 8: 0.5757814 0.82122120
## 9: 0.7383247 0.94383621
## 10: 1.5952808 -2.21469989
I can even write a function that will return a column of the data.table as a vector when passed the name of a column as a character vector:
get.a.vector <- function( my.dt, my.column ) {
## Step 1: Convert my.column to an expression
column.exp <- parse(text=my.column)
## Step 2: Return the vector
return( my.dt[, eval(column.exp)] )
}
get.a.vector( test.data, 'X')
## [1] -0.8356286 -0.8204684 -0.6264538 -0.3053884 0.1836433 0.3295078
## [7] 0.4874291 0.5757814 0.7383247 1.5952808
But I cannot pull a similar trick for list(). The inline comments are the output from the interactive browser() session.
get.a.dt <- function( my.dt, my.column ) {
## Step 1: Convert my.column to an expression
column.exp <- parse(text=my.column)
## Step 2: Enter the browser to play around
browser()
## Step 3: Verity that a literal X works:
my.dt[, list(X)]
## << not shown >>
## Step 4: Attempt to evaluate the parsed experssion
my.dt[, list( eval(column.exp)]
## Error in `rownames<-`(`*tmp*`, value = paste(format(rn, right = TRUE), (from data.table.example.R@1032mCJ#7) :
## length of 'dimnames' [1] not equal to array extent
return( my.dt[, list(eval(column.exp))] )
}
get.a.dt( test.data, "X" )
What am I missing?
Update:
Due to some confusion as to why I would want to do this I wanted to clarify. My use case is when I need to access a data.table column when when I generate the name. Something like this:
set.seed(2)
test.data[, X.1 := rnorm(10)]
which.column <- 'X'
new.column <- paste(which.column, '.1', sep="")
get.a.dt( test.data, new.column )
Hopefully that helps.