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

df$x <- NULL

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

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

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

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

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


当前回答

使用折叠包中的fselect函数的另一个选项。下面是一个可重复的例子:

DF <- data.frame(
  x=1:10,
  y=10:1,
  z=rep(5,10),
  a=11:20
)

library(collapse)
fselect(DF, -z)
#>     x  y  a
#> 1   1 10 11
#> 2   2  9 12
#> 3   3  8 13
#> 4   4  7 14
#> 5   5  6 15
#> 6   6  5 16
#> 7   7  4 17
#> 8   8  3 18
#> 9   9  2 19
#> 10 10  1 20

于2022-08-26与reprex v2.0.2创建

其他回答

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

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

这就给出了一个数据帧

subset(df, select=-y)

但这给出了一个向量

df[,-2]

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

你可以使用一个简单的名字列表:

DF <- data.frame(
  x=1:10,
  y=10:1,
  z=rep(5,10),
  a=11:20
)
drops <- c("x","z")
DF[ , !(names(DF) %in% drops)]

或者,你可以把它们列一个列表,并按名字引用它们:

keeps <- c("y", "a")
DF[keeps]

编辑: 对于那些还不熟悉索引函数的drop参数的人,如果你想保留一列作为一个数据帧,你可以:

keeps <- "y"
DF[ , keeps, drop = FALSE]

drop=TRUE(或不提到它)将删除不必要的维度,因此返回一个具有y列值的向量。

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

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

基于grep()将返回数字向量这一事实,有一种可能更强大的策略。如果你有一个很长的变量列表,就像我在我的数据集中做的那样,一些变量以“。A和其他以。结尾的。B"你只想要以。结尾的。A”(连同所有不符合任何一种模式的变量,这样做:

dfrm2 <- dfrm[ , -grep("\\.B$", names(dfrm)) ]

对于手头的情况,使用Joris Meys的例子,它可能没有那么紧凑,但它将是:

DF <- DF[, -grep( paste("^",drops,"$", sep="", collapse="|"), names(DF) )]