根据向量中的 *not* 选择 R 数据框中的列

Posted

技术标签:

【中文标题】根据向量中的 *not* 选择 R 数据框中的列【英文标题】:Selecting columns in R data frame based on those *not* in a vector 【发布时间】:2012-08-25 20:14:27 【问题描述】:

我很熟悉能够像这样从 R 数据框(或矩阵)中提取列:

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

但是可以使用! 或其他工具来选择除了那些列出的列之外的所有列

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

在我可以删除少数人的情况下输入大多数人的名字 使用更短的df.2 &lt;- 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")]

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

【问题讨论】:

我通常使用自定义中缀运算符缩短您的最后一个示例:'%ni%' &lt;- Negate('%in%') @joran 不是只缩短了! 吗?还是我错过了什么? 是的,虽然大多数人使用 () 所以他们会节省另一个 2。它更多地是关于我的可读性。 最后一个似乎不适用于data.table的fread。 最后一个不适用于data.table的fread。对于 data.table,我得到了它与 here (with=FALSE) 的配合。 我希望有一些独立于包的解决方案。 【参考方案1】:

grep 的替代品是which

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

【讨论】:

此处的技术与 Data.table 中的技术相同,但多了一个逗号,例如 myData[,,!removeCols]【参考方案2】:

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

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

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

【讨论】:

【参考方案3】:

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

【讨论】:

不确定这是否比其他的更清晰/更优越,但我很高兴在新的 [ish] 工具问世时进行更新!感谢您添加此内容以保持新鲜感。【参考方案4】:

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

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

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

【讨论】:

data.frame 方法在其他方面与 data.table 相同,因此 subset(myData,,!names(myData) %in% removeCols) 有一个逗号差异,非常相似。但是这种select=-c(..) 的方法不起作用,为什么? 嗯,不知道!我不使用 data.table 的【参考方案5】:

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

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)

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

【讨论】:

【参考方案6】:

我想到的最简单的方法:

filtered_df

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

【讨论】:

以上是关于根据向量中的 *not* 选择 R 数据框中的列的主要内容,如果未能解决你的问题,请参考以下文章

什么函数允许我根据R中列中的值从数据框中的列中提取数据?

根据向量中的值从数据框中选择行

将 R 中的数据帧连接/合并为向量类型单元格

如何根据数据框中的列值获取特定的行数[重复]

如何根据列的值对熊猫数据框中的列进行分类?

如何根据条件选择R数据框中的连续行?