从向量中删除向量元素

11
这看起来很容易,但是我一直碰到困难。 我有数值向量 v1
v1 <- c(1,1,3,5,7,7)

我有一个数值向量v2。v2始终是v1的子集
我想从v1中删除所有来自v2的元素,但每个v2元素仅删除一个(而且确切地说只有一个)v1元素。

期望的输出

如果v2 <- c(3,5),我希望保留v1中的c(1,1,7,7)。这很容易使用v1[-match(v2,v1)]实现。
如果v2 <- c(1,7),我想保留v1中的c(1,3,5,7)。同样,v1[-match(v2,v1)]也能做到。
如果v2 <- c(1,1),我想从v1中保留c(3,5,7,7)。现在v1[-match(v2,v1)]返回[1] 1 3 5 7 7,不是我想要的。

4个回答

9
你可以使用“vecsets”库中的 vsetdiff(相对于 setdiff,它会保留重复项),方式如下:
library(vecsets)
v1 <- c(1,1,3,5,7,7)
v2.1 <- c(3,5)
> vsetdiff(v1, v2.1)
[1] 1 1 7 7
v2.2 <- c(1,7)
> vsetdiff(v1, v2.2)
[1] 1 3 5 7
v2.3 <- c(1,1)
> vsetdiff(v1, v2.3)
[1] 3 5 7 7

感谢指向 vecsets 包。我可以更经常地使用那些函数。 - Wimpel
@Wimpel 当然,这是一个非常有用的包! - David
@DavidS,你的setdiff方法似乎不起作用,因为它给出了v2 <- c(1,3,7) - ThomasIsCoding
@ThomasIsCoding 你说得对,我没有测试更多的边缘情况,很奇怪,即使 v2<-c(1,3) 也不能正常工作。可能是一个 bug。 - David
1
你可以只保留 vsetdiff 的解决方案,因为我认为 setdiff 无法给出一个适当的方法来解决这个问题。你可以尝试使用 Map("*",1:5,c(-1,1)) 来了解 Map 的工作原理。你在 setdiff 解决方案中的情况只是一个非常特殊的情况,碰巧起作用。 - ThomasIsCoding

5
Reduce(function(x, y) x[-match(y, x)], v2, init = v1)

4

可能有更好的方法使用真正的递归函数,但我认为您可以通过for循环完成此操作:

v1 <- c(1, 1, 3, 5, 7, 7)
v2 <- c(1,1)
v1_keep <- v1

for (i in seq_along(v2)){
  v1_keep <- v1_keep[-match(v2[i], v1_keep)]
}

v1_keep
# [1] 3 5 7 7

1
我尽量避免使用for循环,因为生产数据比这里给出的样本要大得多。但是还是要加1分,因为提供了所需的输出答案。 - Wimpel

2
使用map2函数
library(purrr)
map2(v1, v2, setdiff) %>% 
     flatten

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接