Selecting a subset of columns in a data.table

Viewed 22007

I'd like to print all the columns of a data table dt except one of them named V3 but don't want to refer to it by number but by name. This is the code that I have:

  dt = data.table(matrix(sample(c(0,1),5,rep=T),50,10))
  dt[,-3,with=FALSE]   #  Is this the only way to not print column "V3"? 

Using the data frame way, one could do this through the code:

  df = data.frame(matrix(sample(c(0,1),5,rep=T),50,10))
  df[,!(colnames(df)%in% c("X3"))]

So, my question is: is there another way to not print one column in a data table without the necessity of refer to it by number? I'd like to find something similar to the data frame syntax I used above but using data table.

5 Answers

From version 1.12.0 onwards, it is also possible to select columns using regular expressions on their names:

iris_DT <- as.data.table(iris)

iris_DT[, .SD, .SDcols = patterns(".e.al")]

To summarize the answer to this question, and also to make it
a) negation-friendly (so that you can also select columns by negation),
b) pipe-line friendly (so that you can use in a pipeline with %>% operator), and
c) so that you can select using both column numbers and column names, these are available options:

library(data.table);

select1 <- function (dt, range)  dt[, range, with=F]
select2 <- function (dt, range)  dt[, ..range]
select3 <- function (dt, range)  dt[, .SD, .SDcols=range] 

dt <- ggplot2::diamonds

range <- 1:3 # or 
range <- dt %>% names %>% .[1:3]

dt %>% select1(range);
dt %>% select2(range); 
dt %>% select3(range); 

dt %>% select1(-range);
dt %>% select2(-range); 
dt %>% select3(-range); # DOES NOT WORK

Also we note that this
dt %>% .[, ..(names(dt)[1:3])] # DOES NOT WORK

Therefore the best (most universal and fast) way to select multiple columns in data.table is the following:

# columns are selected using column numbers:
range <- 1:3
dt %>% select1(range); 
dt %>% .[, range, with=F]

# The same works if columns are selected using column names:
range <- names(dt) [1:3]
dt %>% select1(range); 
dt %>% .[, range, with=F]

PS. If, instead of selecting multiple columns, you want to efficiently delete multiple columns from data.table by reference (i.e. instead of copying the entire data.table), then you can use data.table's := operator. But I don't know how to do it for multiple columns in one line

Related