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

df$x <- NULL

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

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

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

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

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


当前回答

另一个数据。还没有发布的表选项使用了特殊的动词。sd,代表数据的子集。与. sdcols参数一起,您可以按名称或索引选择/删除列。

require(data.table)
# data
dt = data.table(
  A = LETTERS[1:5],
  B = 1:5,
  C = rep(TRUE, 5)
)
# delete B
dt[ , .SD, .SDcols =! 'B' ]
# delete all matches (i.e. all columns)
cols = grep('[A-Z]+', names(dt), value = TRUE)
dt[ , .SD, .SDcols =! cols ]

数据中此类任务的所有选项的摘要。表格可以在这里找到

其他回答

还有一个子集命令,如果你知道你想要哪些列,它很有用:

df <- data.frame(a = 1:10, b = 2:11, c = 3:12)
df <- subset(df, select = c(a, c))

要删除列a,c,你可以这样做:

df <- subset(df, select = -c(a, c))

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

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

这就给出了一个数据帧

subset(df, select=-y)

但这给出了一个向量

df[,-2]

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

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

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

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

BBmisc::dropNamed(df, "x")

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

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

如果你有一个大的data.frame和低内存使用[. . . .或rm和within删除data.frame的列,因为子集目前(R 3.6.2)使用更多的内存-除了手册提示交互式使用子集。

getData <- function() {
  n <- 1e7
  set.seed(7)
  data.frame(a = runif(n), b = runif(n), c = runif(n), d = runif(n))
}

DF <- getData()
tt <- sum(.Internal(gc(FALSE, TRUE, TRUE))[13:14])
DF <- DF[setdiff(names(DF), c("a", "c"))] ##
#DF <- DF[!(names(DF) %in% c("a", "c"))] #Alternative
#DF <- DF[-match(c("a","c"),names(DF))]  #Alternative
sum(.Internal(gc(FALSE, FALSE, TRUE))[13:14]) - tt
#0.1 MB are used

DF <- getData()
tt <- sum(.Internal(gc(FALSE, TRUE, TRUE))[13:14])
DF <- subset(DF, select = -c(a, c)) ##
sum(.Internal(gc(FALSE, FALSE, TRUE))[13:14]) - tt
#357 MB are used

DF <- getData()
tt <- sum(.Internal(gc(FALSE, TRUE, TRUE))[13:14])
DF <- within(DF, rm(a, c)) ##
sum(.Internal(gc(FALSE, FALSE, TRUE))[13:14]) - tt
#0.1 MB are used

DF <- getData()
tt <- sum(.Internal(gc(FALSE, TRUE, TRUE))[13:14])
DF[c("a", "c")]  <- NULL ##
sum(.Internal(gc(FALSE, FALSE, TRUE))[13:14]) - tt
#0.1 MB are used