r中删除列 - r语言如何删掉列




按名称删除数据框列 (11)

我有一些我想从数据框中删除的列。 我知道我们可以使用类似的方法单独删除它们:

df$x <- NULL

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

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

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

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

鉴于R是多么强大,我认为可能有比逐个删除每列更好的方法。


Bernd Bischl的BBmisc软件包中有一个名为dropNamed()BBmisc ,完全可以做到这一点。

BBmisc::dropNamed(df, "x")

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

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

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

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值的向量。


出于兴趣,这标志着R的奇怪的多个语法不一致之一。 例如给出一个两列数据框:

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

这给出了一个数据框

subset(df, select=-y)

但是这给出了一个向量

df[,-2]

这是所有的解释?[但它不是完全预期的行为。 至少不对我来说...


列表(NULL)也起作用:

dat <- mtcars
colnames(dat)
# [1] "mpg"  "cyl"  "disp" "hp"   "drat" "wt"   "qsec" "vs"   "am"   "gear"
# [11] "carb"
dat[,c("mpg","cyl","wt")] <- list(NULL)
colnames(dat)
# [1] "disp" "hp"   "drat" "qsec" "vs"   "am"   "gear" "carb"

另一种可能:

df <- df[, setdiff(names(df), c("a", "c"))]

要么

df <- df[, grep('^(a|c)$', names(df), invert=TRUE)]

另一种解决方案,如果你不想使用上面的@ hadley:如果“COLUMN_NAME”是你想删除的列的名称:

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

如果你想通过引用删除列,并避免与data.frames相关的内部复制,那么你可以使用data.table包和函数:=

您可以将字符向量名称传递给:=运算符的左侧,并将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.table的开销, 并且也适用于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=1:10, c=1:10, d=1:10)

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

还有subset命令,如果你知道你想要哪些列,这个命令很有用:

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

在@hadley发表评论后进行更新:要删除列a,您可以执行以下操作:

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

这是一个有关它的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()

我喜欢这一点,因为它可以直观地阅读和理解,而不需要注释,并且可以在数据框内改变列的位置。 它也遵循矢量化惯用法-使用-去除元素。


within(df, rm(x))

可能是最简单的,或者对于多个变量:

within(df, rm(x, y))

或者如果你正在处理data.table s(按照如何在data.table中按名称删除列 ) ?

dt[, x := NULL]   # deletes column x by reference instantly

dt[, !"x", with=FALSE]   # selects all but x into a new data.table

或者用于多个变量

dt[, c("x","y") := NULL]

dt[, !c("x", "y"), with=FALSE]

data.table的开发版本( 安装说明 )中, with = FALSE不再是必要的:

dt[ , !"x"]
dt[ , !c("x", "y")]




r-faq