An idiom for conditionally selecting columns from a data table.

I use the following idiom to conditionally select columns from data.frame:

DF = data.frame(a = 1:3,b = letters[1:3],c = LETTERS[1:3]) someCondition <- FALSE # use `if(someCondition)` to conditionally include column 'c' DF[,c('a','b',if(someCondition)'c')] :> ab :> 1 1 a :> 2 2 b :> 3 3 c 

but the equivalent does not work with data.table b / c NULL values ​​are not dropped from lists the same way they drop out of concatenation:

 DT = as.data.table(DF) DT[,.(a,b,if(someCondition)c)] :> Error in setnames(jval, jvnames) : :> Can't assign 3 names to a 2 column data.table 

I defined a function called .. that works:

 .. <- function(...){ x = list(...) x= x[!sapply(x,is.null)] x } DT[,..(a,b,if(someCondition)c)] :> V1 V2 :> 1: 1 a :> 2: 2 b :> 3: 3 c 

but he is looking like kludgy to include my own function to perform the operation, which is so common. Is there a more idiomatic way to conditionally select columns from a data table.

+7
r data.table
source share
1 answer

I think the argument .SDcols does what you want. In the above example for data.table DF,

 DF[, .SD, .SDcols= c("a","b", if(someCondition) "c")] 

Will act the same as in your data.frame. You can also implement this, as in the example below.

 DF[, .SD, .SDcols=if(someCondition) c("a","b","c") else c("a","b")] 

will make the required selection. In the previous line, you could create more complex constructions of true and false vectors (which could lead to the failure of the goal of preserving the essence).

+2
source share

All Articles