Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Idiom for conditionally selecting columns from a data.table

Tags:

r

data.table

I use the following idiom for conditionally selecting columns from a 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')] 
:>   a b
:> 1 1 a
:> 2 2 b
:> 3 3 c

but the equivalent does not work with data.table's b/c NULL values are not dropped from lists the same way they are dropped from 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've defined a function called .. which is a work around:

.. <- 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 it seeks kind of kludgy to have to include my own function to accomplish an operation that is so common. Is there a more idiomatic way of conditionally selecting columns from a data.table?

like image 867
Jthorpe Avatar asked Oct 26 '15 17:10

Jthorpe


1 Answers

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

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

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

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

will perform the desired selection. In a previous line, you could set up more elaborate constructions of the true and false vectors (which might defeat the purpose of keeping thing succinct).

like image 68
lmo Avatar answered Nov 19 '22 03:11

lmo