通过名称删除数据框列

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

df$x <- NULL 

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

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

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

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

鉴于R是多么强大,我认为可能比逐一删除每一列更好。

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

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

还有subset命令,如果你知道你想要的列是有用的:

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

在@hadley评论之后更新: 删除列a,c你可以这样做:

 df <- subset(df, select = -c(a,c) ) 
 within(df, rm(x)) 

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

 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 

或者用于多个variables

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

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

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

你可以像这样使用%in%

 df[, !(colnames(df) %in% c("x","bar","foo"))] 

列表(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" 

如果你想通过引用删除列,并避免与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) 

有一个潜在的更强大的策略基于这样的事实,即grep()将返回一个数字向量。 如果你有一长串variables,就像我在其中一个数据集中做的那样,一些以“.A”结尾的variables和其他以“.B”结尾的variables,你只需要那些以“.A”结尾的variables与所有不符合任何模式的variables,请执行以下操作:

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

对于目前的情况,使用Joris Meys的例子,它可能不是那么紧凑,但它可能是:

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

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

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

这给出了一个数据框架

 subset(df, select=-y) 

但是这给了一个向量

 df[,-2] 

这是所有的解释?[但它不是完全预期的行为。 那么至less不要对我…

另一个dplyr答案。 如果你的variables有一些通用的命名结构,你可以试试starts_with() 。 例如

 library(dplyr) df <- data.frame(var1 = rnorm(5), var2 = rnorm(5), var3 = rnorm (5), var4 = rnorm(5), char1 = rnorm(5), char2 = rnorm(5)) df # var2 char1 var4 var3 char2 var1 #1 -0.4629512 -0.3595079 -0.04763169 0.6398194 0.70996579 0.75879754 #2 0.5489027 0.1572841 -1.65313658 -1.3228020 -1.42785427 0.31168919 #3 -0.1707694 -0.9036500 0.47583030 -0.6636173 0.02116066 0.03983268 df1 <- df %>% select(-starts_with("char")) df1 # var2 var4 var3 var1 #1 -0.4629512 -0.04763169 0.6398194 0.75879754 #2 0.5489027 -1.65313658 -1.3228020 0.31168919 #3 -0.1707694 0.47583030 -0.6636173 0.03983268 

如果要在数据框中放置一系列variables,可以使用: 。 例如,如果您想要在其中放置var2var3所有variables,那么您只需要使用var1

 df2 <- df1 %>% select(-c(var2:var3) ) df2 # var1 #1 0.75879754 #2 0.31168919 #3 0.03983268 
 DF <- data.frame( x=1:10, y=10:1, z=rep(5,10), a=11:20 ) DF 

输出:

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

输出:

  yz 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 

另一种可能性

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

要么

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

这是一个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() 

我喜欢这个,因为它直观地阅读和理解没有注释和强大的列改变数据框架内的位置。 它也遵循向量化的习惯用法-去除元素。

我一直认为必须有一个更好的习惯用法,但是为了减less名称的列,我倾向于做到以下几点:

 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就是这样做的。

 BBmisc::dropNamed(df, "x") 

优点是避免重复dataframe参数,因此适用于magrittrpipe道(就像dplyr方法一样):

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

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

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