如何在data.table中按名称删除列?

时间:2012-02-08 22:20:31

标签: r data.table

要删除data.frame中名为“foo”的列,我可以这样做:

df <- df[-grep('foo', colnames(df))]

但是,将df转换为data.table对象后,无法删除列。

示例:

df <- data.frame(id = 1:100, foo = rnorm(100))
df2 <- df[-grep('foo', colnames(df))] # works
df3 <- data.table(df)
df3[-grep('foo', colnames(df3))] 

但是一旦它被转换为data.table对象,它就不再起作用了。

8 个答案:

答案 0 :(得分:246)

以下任何一项都会从data.table foo中删除列df3

# Method 1 (and preferred as it takes 0.00s even on a 20GB data.table)
df3[,foo:=NULL]

df3[, c("foo","bar"):=NULL]  # remove two columns

myVar = "foo"
df3[, (myVar):=NULL]   # lookup myVar contents

# Method 2a -- A safe idiom for excluding (possibly multiple)
# columns matching a regex
df3[, grep("^foo$", colnames(df3)):=NULL]

# Method 2b -- An alternative to 2a, also "safe" in the sense described below
df3[, which(grepl("^foo$", colnames(df3))):=NULL]

data.table 还支持以下语法:

## Method 3 (could then assign to df3, 
df3[, !"foo", with=FALSE]  

但如果你真的想要从"foo"中移除列df3(而不是只打印df3减去列"foo"的视图),那么你真的想要改为使用方法1。

(请注意,如果您使用依赖grep()grepl()的方法,则需要设置pattern="^foo$"而不是"foo",如果您不想要列使用"fool""buffoon"等名称(即包含foo作为子字符串的名称)也可以匹配和删除。)

安全性较低的选项,适合交互式使用:

接下来的两个习语也可以使用 - 如果df3包含匹配"foo" 的列 - 但如果没有,则会以可能意外的方式失败。例如,如果您使用其中任何一个来搜索不存在的列"bar",则最终会得到一个零行data.table。

因此,它们最适合交互式使用,例如,人们可能希望显示data.table减去名称中包含子字符串"foo"的任何列。出于编程目的(或者如果您想要从df3而不是从其副本中删除列),方法1,2a和2b确实是最佳选择。

# Method 4a:
df3[, -grep("^foo$", colnames(df3)), with=FALSE]

# Method 4b: 
df3[, !grepl("^foo$", colnames(df3)), with=FALSE]

答案 1 :(得分:29)

您也可以使用set来避免循环中[.data.table的开销:

dt <- data.table( a=letters, b=LETTERS, c=seq(26), d=letters, e=letters )
set( dt, j=c(1L,3L,5L), value=NULL )
> dt[1:5]
   b d
1: A a
2: B b
3: C c
4: D d
5: E e

如果您想按列名称进行操作,which(colnames(dt) %in% c("a","c","e"))应适用于j

答案 2 :(得分:16)

我只是在数据框中这样做:

DT$col = NULL

快速工作,据我所知,不会造成任何问题。

更新:如果你的DT非常大,不是最好的方法,因为使用$<-运算符会导致对象复制。所以更好用:

DT[, col:=NULL]

答案 3 :(得分:5)

非常简单的选项,以防您在数据表中删除多个单独的列,并且您希望避免键入所有列名称#careadviced

dt <- dt[, -c(1,4,6,17,83,104), with =F]

这将取代基于列号的列。

它显然不那么有效,因为它绕过了data.table优势,但如果你的工作少于500,000行,那就可以了。

答案 4 :(得分:0)

假设您的dt包含col1col2col3col4col5coln列。

删除其中的一部分:

vx <- as.character(bquote(c(col1, col2, col3, coln)))[-1]
DT[, paste0(vx):=NULL]

答案 5 :(得分:-2)

如果要根据列名称将列数设置为NULL,可以使用以下方法 适合您的用途:)

deleteColsFromDataTable&lt; - function(train,toDeleteColNames){

   for (myNm in toDeleteColNames)

   train <- train [,(myNm):=NULL,with=F]

   return (train)

}

答案 6 :(得分:-2)

DT[,c:=NULL] # remove column c

答案 7 :(得分:-7)

对于data.table,将列指定为NULL会将其删除:

DT[,c("col1", "col1", "col2", "col2")] <- NULL
^
|---- Notice the extra comma if DT is a data.table

......相当于:

DT$col1 <- NULL
DT$col2 <- NULL
DT$col3 <- NULL
DT$col4 <- NULL

data.frame的等价物是:

DF[c("col1", "col1", "col2", "col2")] <- NULL
      ^
      |---- Notice the missing comma if DF is a data.frame

Q值。为什么data.table的版本中有逗号,而data.frame的版本中没有逗号?

一个。由于data.frames存储为列列表,因此您可以跳过逗号。您也可以添加它,但是您需要将它们分配到NULL s DF[, c("col1", "col2", "col3")] <- list(NULL)的列表中。