【发布时间】:2012-03-28 18:55:26
【问题描述】:
我有一个向量,例如:a = c(1:10),我需要删除多个值,例如:2, 3, 5
如何删除向量中的那些数字(它们不是向量中的位置)?
此刻我循环向量并执行以下操作:
a[!a=NUMBER_TO_REMOVE]
但我认为有一个功能可以自动完成。
【问题讨论】:
标签: r
我有一个向量,例如:a = c(1:10),我需要删除多个值,例如:2, 3, 5
如何删除向量中的那些数字(它们不是向量中的位置)?
此刻我循环向量并执行以下操作:
a[!a=NUMBER_TO_REMOVE]
但我认为有一个功能可以自动完成。
【问题讨论】:
标签: r
%in% 运算符告诉您要删除的数字中有哪些元素:
> a <- sample (1 : 10)
> remove <- c (2, 3, 5)
> a
[1] 10 5 2 7 1 6 3 4 8 9
> a %in% remove
[1] FALSE TRUE TRUE FALSE FALSE FALSE TRUE FALSE FALSE FALSE
> a [! a %in% remove]
[1] 10 7 1 6 4 8 9
请注意,这将默默地删除无法比较的值(NA 或 Inf) 之类的东西(同时它会在 a 中保留重复值,只要它们未在 remove 中列出)。
如果a 可以包含不可比值,但remove 不能,我们可以使用match,告诉它返回0 用于不匹配和不可比值(%in% 是match 的方便快捷方式):
> a <- c (a, NA, Inf)
> a
[1] 10 5 2 7 1 6 3 4 8 9 NA Inf
> match (a, remove, nomatch = 0L, incomparables = 0L)
[1] 0 3 1 0 0 0 2 0 0 0 0 0
> a [match (a, remove, nomatch = 0L, incomparables = 0L) == 0L]
[1] 10 7 1 6 4 8 9 NA Inf
incomparables = 0 不是需要,因为无论如何都无法匹配,但为了便于阅读,我会包含它。
顺便说一句,这是 setdiff 在内部所做的(但没有 unique 来丢弃 a 中不在 remove 中的重复项)。
如果remove 包含无与伦比的内容,您必须单独检查它们,例如
if (any (is.na (remove)))
a <- a [! is.na (a)]
(这并不能区分 NA 和 NaN,但 R 手册无论如何都警告说,不应依赖它们之间的差异)
对于Inf/ -Inf,您必须同时检查sign 和is.finite
【讨论】:
setdiff 更好,因为它在一个操作中完成所有操作,并且只引用一次修改后的向量。
a 中不在 remove 中的重复项。如果这不是问题,您也可以使用setdiff。 setdiff,顺便说一句,使用match,其中%in% 是一个快捷方式。
您可以使用setdiff。
给定
a <- sample(1:10)
remove <- c(2, 3, 5)
然后
> a
[1] 10 8 9 1 3 4 6 7 2 5
> setdiff(a, remove)
[1] 10 8 9 1 4 6 7
【讨论】:
a 是另一个函数的结果时非常有用,因此您可以在一行中执行操作,而不是 3 和一个临时变量
%in% 解决方案不同的结果(在这种情况下,setdiff 将只返回唯一的 set,即没有重复项)
fsetdiff of data.table 包有一个 all 标志(默认 F),允许在输入向量中保留重复项。
你可以这样做:
> x<-c(2, 4, 6, 9, 10) # the list
> y<-c(4, 9, 10) # values to be removed
> idx = which(x %in% y ) # Positions of the values of y in x
> idx
[1] 2 4 5
> x = x[-idx] # Remove those values using their position and "-" operator
> x
[1] 2 6
很快
> x = x[ - which(x %in% y)]
【讨论】:
which。和@cbeleites 的回答基本一样。
which 返回 TRUE 值的索引。所以减号可以用来表示“这些索引以外的索引”。此外,which 更易于阅读,因为它更接近自然语言。
而不是
x <- x[! x %in% c(2,3,5)]
使用包purrr 和magrittr,您可以:
your_vector %<>% discard(~ .x %in% c(2,3,5))
这允许subsetting 只使用一次向量名称。你可以在管道中使用它:)
【讨论】:
首先我们可以定义一个新的操作符,
"%ni%" = Negate( "%in%" )
然后,它就像 x 不在删除中
x <- 1:10
remove <- c(2,3,5)
x <- x[ x %ni% remove ]
或者为什么要去remove,直接去
x <- x[ x %ni% c(2,3,5)]
【讨论】:
还有 subset 有时可能有用:
a <- sample(1:10)
bad <- c(2, 3, 5)
> subset(a, !(a %in% bad))
[1] 9 7 10 6 8 1 4
【讨论】:
更新:
以上所有答案都不适用于重复值,@BenBolker 使用 duplicated() 谓词的答案解决了这个问题:
full_vector[!full_vector %in% searched_vector | duplicated(full_vector)]
原答案: 这里我为此写了一个小函数:
exclude_val<-function(full_vector,searched_vector){
found=c()
for(i in full_vector){
if(any(is.element(searched_vector,i))){
searched_vector[(which(searched_vector==i))[1]]=NA
}
else{
found=c(found,i)
}
}
return(found)
}
所以,假设full_vector=c(1,2,3,4,1) 和searched_vector=c(1,2,3)。
exclude_val(full_vector,searched_vector) 将返回 (4,1),但上述答案将仅返回 (4)。
【讨论】:
full_vector[!full_vector %in% searched_vector | duplicated(full_vector)] 呢?
full_vector = c(1,1,1,2,3); searched_vector = c(1,1,3); - 产生1, 1, 2 而不是正确答案1, 2。
removeif <- function(from, where) { for (i in where) if (i %in% from) {from = from[-match(i, from)]}; from}
q <- c(1,1,2,2,3,3,3,4,4,5,5,7,7)
rm <- q[11]
remove(rm)
q
q[13] = NaN
q
q %in% 7
这会将向量中的 13 设置为不是数字(NAN),它显示为 false 移除(q[c(11,12,13)]) 如果你尝试这个,你会看到删除功能不适用于向量编号。 您删除了整个向量,但可能没有删除单个元素。
【讨论】: