53

我熟悉能够从 R 数据框(或矩阵)中提取列,如下所示:

df.2 <- df[, c("name1", "name2", "name3")]

但是可以使用一种!或其他工具来选择除列出的列之外的所有列吗?

作为背景,我有一个包含很多列向量的数据框,我想避免:

  • 当我可以删除少数人时,输入大多数人的名字
  • 使用更短的df.2 <- df[, c(1,3,5)],因为当我的 .csv 文件更改时,我的代码会因为编号不再相同而变得糟糕。我是 R 新手,我认为我已经学会了不使用数字向量来处理可能会改变的较大 df 的艰难方法。

我试过了:

df.2 <- df[, !c("name1", "name2", "name3")]
df.2 <- df[, !=c("name1", "name2", "name3")]

就在我输入这个的时候,发现这行得通:

df.2 <- df[, !names(df) %in% c("name1", "name2", "name3")]

有没有比这最后一个更好的方法?

4

6 回答 6

36

一种替代方法grepwhich

df.2 <- df[, -which(names(df) %in% c("name1", "name2", "name3"))]
于 2012-08-31T18:12:26.240 回答
12

您可以使用negative-grep 进行更短的调用:

df.2 <- df[, -grep("^name[1:3]$", names(df) )] 

由于 grep 返回数字,您可以使用负向量索引来删除列。您可以添加更多数量或更复杂的模式。

于 2012-08-31T04:58:00.960 回答
11

dplyr::select()有几个用于删除特定列的选项:

library(dplyr)

drop_columns <- c('cyl','disp','hp')
mtcars %>% 
  select(-one_of(drop_columns)) %>% 
  head(2)

              mpg drat    wt  qsec vs am gear carb
Mazda RX4      21  3.9 2.620 16.46  0  1    4    4
Mazda RX4 Wag  21  3.9 2.875 17.02  0  1    4    4

否定特定的列名,以下删除列“hp”和从“qsec”到“gear”的列:

mtcars %>% 
  select(-hp, -(qsec:gear)) %>% 
  head(2)

              mpg cyl disp drat    wt carb
Mazda RX4      21   6  160  3.9 2.620    4
Mazda RX4 Wag  21   6  160  3.9 2.875    4

你也可以否定 contains(), starts_with(), ends_with(), 或matches():

mtcars %>% 
  select(-contains('t')) %>%
  select(-starts_with('a')) %>% 
  select(-ends_with('b')) %>% 
  select(-matches('^m.+g$')) %>% 
  head(2)

              cyl disp  hp  qsec vs gear
Mazda RX4       6  160 110 16.46  0    4
Mazda RX4 Wag   6  160 110 17.02  0    4
于 2018-03-09T15:22:17.850 回答
4

旧线程,但这是另一个解决方案:

df.2 <- subset(df, select=-c(name1, name2, name3))

这是在另一个类似的帖子中发布的(尽管我现在找不到它)。在您描述的情况下应该是可持续的代码,并且可能比其他一些选项更容易阅读和编辑。

于 2017-04-25T00:32:16.860 回答
2

如果您自己使用它来操作数据,您可以创建一个自定义函数来执行此操作。我可能会做这样的事情:

rm.col <- function(df, ...) {
    x <- substitute(...())
    z <- Trim(unlist(lapply(x, function(y) as.character(y))))
    df[, !names(df) %in% z]
}

rm.col(mtcars, hp, mpg)

第一个参数是数据框名称。以下...是您要删除的任何列的名称。

于 2012-08-31T02:42:56.753 回答
0

我想到的最简单的方法:

过滤_df<-df[, setdiff(names(df),c("name1","name2") ]

本质上,您正在计算列名的完整列表和要过滤掉的子集(上面的 name1 和 name2)之间的差异。

于 2015-11-08T01:18:41.517 回答