根据向量中的 *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 <- 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%' <- 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 数据框中的列的主要内容,如果未能解决你的问题,请参考以下文章