【问题标题】:How to delete multiple values from a vector?如何从向量中删除多个值?
【发布时间】:2012-03-28 18:55:26
【问题描述】:

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

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

此刻我循环向量并执行以下操作:

a[!a=NUMBER_TO_REMOVE]

但我认为有一个功能可以自动完成。

【问题讨论】:

    标签: r


    【解决方案1】:

    %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
    

    请注意,这将默默地删除无法比较的值(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 中不在 remove 中的重复项)。

    • 如果remove 包含无与伦比的内容,您必须单独检查它们,例如

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

      (这并不能区分 NANaN,但 R 手册无论如何都警告说,不应依赖它们之间的差异)

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

    【讨论】:

    • setdiff 更好,因为它在一个操作中完成所有操作,并且只引用一次修改后的向量。
    • @Olexa:设置差异并不总是与从向量中删除给定数字集的所有出现相同:它也会删除 a 中不在 remove 中的重复项。如果这不是问题,您也可以使用setdiffsetdiff,顺便说一句,使用match,其中%in% 是一个快捷方式。
    【解决方案2】:

    您可以使用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,即没有重复项)
    • @docendodiscimus: fsetdiff of data.table 包有一个 all 标志(默认 F),允许在输入向量中保留重复项。
    【解决方案3】:

    你可以这样做:

    > 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 更易于阅读,因为它更接近自然语言。
    【解决方案4】:

    而不是

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

    使用包purrrmagrittr,您可以:

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

    这允许subsetting 只使用一次向量名称。你可以在管道中使用它:)

    【讨论】:

    • 你能解释一下你关于变量名称长度的最后陈述吗?为什么你不喜欢那样?为什么比其他方式更好?或者,删除该段落,因为与主要问题/问题无关。
    【解决方案5】:

    首先我们可以定义一个新的操作符,

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

    【讨论】:

    • 问题具体说2、3、5不是向量中的位置。
    【解决方案6】:

    还有 subset 有时可能有用:

    a <- sample(1:10)
    bad <- c(2, 3, 5)
    
    > subset(a, !(a %in% bad))
    [1]  9  7 10  6  8  1  4
    

    【讨论】:

      【解决方案7】:

      更新:

      以上所有答案都不适用于重复值,@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)] 呢?
      • @BenBolker 啊,我不知道那个“重复的”谓词:((现在该怎么办,我应该删除我的答案还是改为只显示你的答案?
      • @BenBolker,您的解决方案是错误的;试试看:full_vector = c(1,1,1,2,3); searched_vector = c(1,1,3); - 产生1, 1, 2 而不是正确答案1, 2
      • 只是为重复值添加一个可能的正确解决方案:removeif &lt;- function(from, where) { for (i in where) if (i %in% from) {from = from[-match(i, from)]}; from}
      【解决方案8】:
      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)​​]) 如果你尝试这个,你会看到删除功能不适用于向量编号。 您删除了整个向量,但可能没有删除单个元素。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2018-03-08
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多