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

df$x <- NULL

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

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

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

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

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


当前回答

如果您希望通过引用删除列并避免与data.frames相关的内部复制,则可以使用数据。表包和函数:=

您可以将字符向量名称传递到:=运算符的左侧,并将NULL作为RHS。

library(data.table)

df <- data.frame(a=1:10, b=1:10, c=1:10, d=1:10)
DT <- data.table(df)
# or more simply  DT <- data.table(a=1:10, b=1:10, c=1:10, d=1:10) #

DT[, c('a','b') := NULL]

如果希望将名称预定义为[调用之外的字符向量,请将对象名称包装在()或{}中,以强制LHS在调用范围内计算,而不是作为DT范围内的名称。

del <- c('a','b')
DT <- data.table(a=1:10, b=1:10, c=1:10, d=1:10)
DT[, (del) := NULL]
DT <-  <- data.table(a=1:10, b=1:10, c=1:10, d=1:10)
DT[, {del} := NULL]
# force or `c` would also work.   

您也可以使用set,这避免了[.data]的开销。表,也适用于data.frames!

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

# drop `a` from df (no copying involved)

set(df, j = 'a', value = NULL)
# drop `b` from DT (no copying involved)
set(DT, j = 'b', value = NULL)

其他回答

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

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))

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

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
df <- data.frame(
+   a=1:5,
+   b=6:10,
+   c=rep(22,5),
+   d=round(runif(5)*100, 2),
+   e=round(runif(5)*100, 2),
+   f=round(runif(5)*100, 2),
+   g=round(runif(5)*100, 2),
+   h=round(runif(5)*100, 2)
+ )
> df
  a  b  c     d     e     f     g     h
1 1  6 22 76.31 39.96 66.62 72.75 73.14
2 2  7 22 53.41 94.85 96.02 97.31 85.32
3 3  8 22 98.29 38.95 12.61 29.67 88.45
4 4  9 22 20.04 53.53 83.07 77.50 94.99
5 5 10 22  5.67  0.42 15.07 59.75 31.21

> # remove cols: d g h
> newDf <- df[, c(1:3, 5), drop=TRUE]
> newDf
  a  b  c     e
1 1  6 22 39.96
2 2  7 22 94.85
3 3  8 22 38.95
4 4  9 22 53.53
5 5 10 22  0.42
DF <- data.frame(
  x=1:10,
  y=10:1,
  z=rep(5,10),
  a=11:20
)
DF

输出:

    x  y z  a
1   1 10 5 11
2   2  9 5 12
3   3  8 5 13
4   4  7 5 14
5   5  6 5 15
6   6  5 5 16
7   7  4 5 17
8   8  3 5 18
9   9  2 5 19
10 10  1 5 20

DF[c("a","x")] <- list(NULL)

输出:

        y z
    1  10 5
    2   9 5
    3   8 5
    4   7 5
    5   6 5
    6   5 5
    7   4 5
    8   3 5    
    9   2 5
    10  1 5

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

BBmisc::dropNamed(df, "x")

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

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