我想从数据帧中删除一些列。我知道我们可以使用如下方法单独删除它们:

df$x <- NULL

但我希望用更少的命令来做到这一点。

另外,我知道我可以像这样使用整数索引删除列:

df <- df[ -c(1, 3:6, 12) ]

但我担心变量的相对位置可能会改变。

考虑到R的强大功能,我认为可能有一种比逐个删除每一列更好的方法。


当前回答

出于兴趣,这标记了R的一个奇怪的多重语法不一致。例如,给定一个两列数据帧:

df <- data.frame(x=1, y=2)

这就给出了一个数据帧

subset(df, select=-y)

但这给出了一个向量

df[,-2]

这些都在?中得到了解释,但这并不是完全预期的行为。至少对我来说不是……

其他回答

使用which找到要删除的列的索引。给这些下标一个负号(*-1)。然后对这些值进行子集化,这将从数据框架中删除它们。这是一个例子。

DF <- data.frame(one=c('a','b'), two=c('c', 'd'), three=c('e', 'f'), four=c('g', 'h'))
DF
#  one two three four
#1   a   d     f    i
#2   b   e     g    j

DF[which(names(DF) %in% c('two','three')) *-1]
#  one four
#1   a    g
#2   b    h

如果你不想使用@hadley's上面的另一个解决方案:如果"COLUMN_NAME"是你想删除的列的名称:

df[,-which(names(df) == "COLUMN_NAME")]

在Bernd Bischl的BBmisc包中有一个名为dropNamed()的函数就是这样做的。

BBmisc::dropNamed(df, "x")

优点是它避免了重复数据帧参数,因此适合在magrittr中管道(就像dplyr方法一样):

df %>% BBmisc::dropNamed("x")

我一直在想一定有更好的习语,但对于按名称减法的列,我倾向于这样做:

df <- data.frame(a=1:10, b=1:10, c=1:10, d=1:10)

# return everything except a and c
df <- df[,-match(c("a","c"),names(df))]
df

下面是一个dplyr方法:

#df[ -c(1,3:6, 12) ]  # original
df.cut <- df %>% select(-col.to.drop.1, -col.to.drop.2, ..., -col.to.drop.6)  # with dplyr::select()

我喜欢这个,因为它是直观的阅读和理解,没有注释和健壮的列在数据框架内改变位置。它还遵循向量化成语使用-来删除元素。