225

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

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对象,它就不再起作用了。

4

8 回答 8

328

foo以下任何一项都会从 data.table中删除列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"]  

但是,如果您实际上想从中删除 column "foo"df3而不是仅打印df3minus column的视图"foo"),您确实想改用方法 1。

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

不太安全的选项,适合交互式使用:

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

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

# Method 4:
df3[, .SD, .SDcols = !patterns("^foo$")]

最后有一些方法使用with=FALSE, 虽然data.table正在逐渐远离使用这个参数,所以现在不鼓励在可以避免的地方使用它;在此处显示,以便您知道该选项是否存在,以防您确实需要它:

# Method 5a (like Method 3)
df3[, !"foo", with=FALSE] 
# Method 5b (like Method 4)
df3[, !grep("^foo$", names(df3)), with=FALSE]
# Method 5b (another like Method 4)
df3[, !grepl("^foo$", names(df3)), with=FALSE]
于 2012-02-08T22:27:00.460 回答
32

您也可以使用它,这样可以避免in 循环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.

于 2013-10-21T20:42:18.340 回答
22

我只是以数据框的方式进行操作:

DT$col = NULL

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

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

DT[, col:=NULL]
于 2013-05-19T20:39:13.233 回答
10

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

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

这将改为根据列号删除列。

它显然没有那么高效,因为它绕过了 data.table 的优势,但是如果您使用的行数少于 500,000 行,它就可以正常工作

于 2015-07-03T02:02:58.083 回答
4

假设您的 dt 有列col1, col2, col3, col4, col5, coln.

要删除其中的一个子集:

vx <- as.character(bquote(c(col1, col2, col3, coln)))[-1]
DT[, paste0(vx):=NULL]
于 2017-02-24T02:30:44.460 回答
-1

这是一种当您想将列数设置为 NULL 时的一种方法,因为它们的列名是您使用的函数:)

deleteColsFromDataTable <- function (train, toDeleteColNames) {

       for (myNm in toDeleteColNames)

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

       return (train)
}
于 2014-04-14T09:22:53.583 回答
-4
DT[,c:=NULL] # remove column c
于 2016-11-15T02:25:00.957 回答
-6

对于 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的版本没有逗号?

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

于 2014-03-31T20:54:23.150 回答