从R中的data.frame中移除整个列

有人知道如何从R中的data。frame中移除一整列吗?例如,如果我得到这个data.frame:

> head(data)
chr       genome region
1 chr1 hg19_refGene    CDS
2 chr1 hg19_refGene   exon
3 chr1 hg19_refGene    CDS
4 chr1 hg19_refGene   exon
5 chr1 hg19_refGene    CDS
6 chr1 hg19_refGene   exon

我想去掉第二列。

1238265 次浏览

你可以将它设置为NULL

> Data$genome <- NULL
> head(Data)
chr region
1 chr1    CDS
2 chr1   exon
3 chr1    CDS
4 chr1   exon
5 chr1    CDS
6 chr1   exon

正如评论中所指出的,这里有一些其他的可能性:

Data[2] <- NULL    # Wojciech Sobala
Data[[2]] <- NULL  # same as above
Data <- Data[,-2]  # Ian Fellows
Data <- Data[-2]   # same as above

你可以通过以下方法删除多个列:

Data[1:2] <- list(NULL)  # Marek
Data[1:2] <- NULL        # does not work!

但是要小心矩阵子集的设置,因为你最终会得到一个向量:

Data <- Data[,-(2:3)]             # vector
Data <- Data[,-(2:3),drop=FALSE]  # still a data.frame

要按名称删除一个或多个列,当列名是已知的(而不是在运行时确定的),我喜欢subset()语法。例如,对于数据帧

df <- data.frame(a=1:3, d=2:4, c=3:5, b=4:6)

来删除a

Data <- subset( Data, select = -a )

和删除bd

Data <- subset( Data, select = -c(d, b ) )

你可以删除db之间的所有列:

Data <- subset( Data, select = -c( d : b )

如上所述,此语法仅在列名已知的情况下有效。当以编程方式确定列名(即赋值给变量)时,它将不起作用。我将从?subset文档中复制这个警告:

警告:

这是一个方便交互使用的函数。 对于编程,最好使用标准子集 像'['这样的函数,特别是非标准求值 的参数“子集”可能会产生意想不到的结果

当使用data.frames时,发布的答案非常好。然而,从内存的角度来看,这些任务的效率非常低。对于大数据,删除列可能需要异常长的时间和/或由于out of memory错误而失败。包data.table通过:=操作符帮助解决这个问题:

library(data.table)
> dt <- data.table(a = 1, b = 1, c = 1)
> dt[,a:=NULL]
b c
[1,] 1 1

我应该用一个更大的例子来说明差异。我会在某个时候更新这个答案。

(为了完整性)如果你想按名称删除列,你可以这样做:

cols.dont.want <- "genome"
cols.dont.want <- c("genome", "region") # if you want to remove multiple columns


data <- data[, ! names(data) %in% cols.dont.want, drop = F]

包含drop = F可以确保结果仍然是data.frame,即使只剩下一列。

这样你就可以删除column并将variable存储到另一个variable中。

df = subset(data, select = -c(genome) )

有几个选项可以使用dplyr::select()和一些辅助函数删除一个或多个列。helper函数可能很有用,因为有些helper函数不需要命名要删除的所有特定列。注意,要使用select()删除列,需要使用前导-对列名求反。

使用dplyr::starwars样本数据对列名的一些变化:

library(dplyr)


starwars %>%
select(-height) %>%                  # a specific column name
select(-one_of('mass', 'films')) %>% # any columns named in one_of()
select(-(name:hair_color)) %>%       # the range of columns from 'name' to 'hair_color'
select(-contains('color')) %>%       # any column name that contains 'color'
select(-starts_with('bi')) %>%       # any column name that starts with 'bi'
select(-ends_with('er')) %>%         # any column name that ends with 'er'
select(-matches('^v.+s$')) %>%       # any column name matching the regex pattern
select_if(~!is.list(.)) %>%          # not by column name but by data type
head(2)


# A tibble: 2 x 2
homeworld species
<chr>     <chr>
1 Tatooine  Human
2 Tatooine  Droid

你也可以按列号下拉:

starwars %>%
select(-2, -(4:10)) # column 2 and columns 4 through 10

我只是想加上一个还没提到的。这很简单,但也很有趣,因为在我所有的互联网阅读中,我没有看到它,即使高度相关的%在%中出现在很多地方。

df <- df[ , -which(names(df) == 'removeCol')]

而且,我没有看到任何人发布grep替代品。这对于删除匹配模式的多个列非常方便。