如何从向量中删除多个值?


125

我有一个向量,例如:a = c(1:10),我需要删除多个值,例如:2, 3, 5

如何删除向量中的那些数字(它们不是向量中的位置)?

目前,我循环矢量并做类似的事情:

a[!a=NUMBER_TO_REMOVE]

但是我认为有一个功能可以自动执行。

Answers:


192

%in%运营商告诉您哪些元素是numers以去除其中:

> 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

请注意,这将无声地删除不可比的值(类似NAInf)一样的东西(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不包含in的重复项remove)。

  • 如果remove包含无与伦比的商品,则必须单独检查它们,例如

    if (any (is.na (remove))) 
      a <- a [! is.na (a)]

    (这NANaN但R手册始终警告说,不应依赖于两者之间的差异)

    对于Inf/,-Inf您必须同时检查signis.finite


1
setdiff更好,因为它一次完成所有操作,并且只引用修改过的向量一次。
Olexa

1
@Olexa:集合差并不总是与从向量中删除给定数字集的所有出现相同:它也将删除a不在其中的重复项remove。如果那不是问题,您也可以使用setdiffsetdiff,顺便说一句,使用match%in%是一个快捷方式。
cbeleites对SX不满意,

97

您可以使用 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

1
a另一个函数的结果何时非常有用,因此您可以一行而不是3和一个temp变量来处理事情
jf328 2015年

14
%in%如果输入向量包含重复项,则将产生与解决方案不同的结果(在这种情况下,setdiff将仅返回唯一的集合,即没有重复项)
talat

2
@docendodiscimus:fsetdiffdata.tablepackage带有一个all标志(默认F),该标志允许将重复项保留在输入向量中。
Juergen '18年

9

您可以按照以下步骤进行操作:

> 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)]

1
您在示例中称为列表的是向量,对吗?
patrick

是的,我的意思是向量。感谢您的评论。
ykpemre '16

这里没有必要which。它基本上与@cbeleites答案相同。
David Arenburg

是的,它是相似的,但是在一些观点上是不同的。which返回TRUE值的索引。因此减号可以用来表示“这些索引以外的索引”。which由于它更接近自然语言,因此也更具可读性。
ykpemre

4

代替

x <- x[! x %in% c(2,3,5)]

使用包purrrmagrittr,你可以这样做:

your_vector %<>% discard(~ .x %in% c(2,3,5))

这仅允许subset一次使用向量名称。您可以在管道中使用它:)


您能否解释一下有关变量名称长度的最后一条语句?你为什么不喜欢那个?为什么比其他方法更好?或者,删除该段落,因为它与主要问题无关。
rodrigoap

2

首先,我们可以定义一个新的运算符,

"%ni%" = Negate( "%in%" )

然后,它像x不在删除

x <- 1:10
remove <- c(2,3,5)
x <- x[ x %ni% remove ]

或为什么要删除,直接去

x <- x[ x %ni% c(2,3,5)]

3
这个问题专门说2、3和5不是向量中的位置。
blakeoft

1

更新:

以上所有答案均不适用于重复值,@ 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)


1
那又如何full_vector[!full_vector %in% searched_vector | duplicated(full_vector)]呢?
本博克

@BenBolker啊我不知道,“复制”谓:((现在该怎么办,我要删除我的答案或将其更改为只显示你的呢?
Özgür的

@BenBolker,您的解决方案是错误的;只需尝试:full_vector = c(1,1,1,2,3); searched_vector = c(1,1,3);-产生1, 1, 2而不是正确的答案1, 2
fnl 2015年

只是为重复的值添加一个可能的正确解决方案:removeif <- function(from, where) { for (i in where) if (i %in% from) {from = from[-match(i, from)]}; from}
fnl 2015年

1
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),它显示错误的remove(q [c(11,12,13)]),如果您尝试执行此操作,将会看到remove函数不适用于向量号。您删除了整个矢量,但可能没有一个元素。


By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.