如何从另一个向量中删除向量中的项目

时间:2018-03-26 10:12:18

标签: r

我有两个向量:

a = c(1,1,2,2,3,3,4,4) 
b = c(1)

我想从b删除a第一个匹配。因此,此处仅从1中删除了第一个a

c = c(1,2,2,3,3,4,4)

a中的项目顺序并不重要。

我试过这段代码:

a[a != b]
a[! a %in% b] 

两个结果都是:

[1] 2 2 3 3 4 4.

删除所有1个数字。但是,我只想从b中删除a中的特定项目。

如果b = c(1, 1, 2),那么我希望结果

[1] 2 3 3 4 4

a[-(1:3)]

上述代码可能会导致[1] 2 3 3 4 4的结果。但是,我希望它可以更灵活。例如,当项目的顺序未知或随机时:

a = c(3,4,3,1,2,2,1,4)

我怎样才能使用R?

5 个答案:

答案 0 :(得分:4)

vecsets包可以执行标准集操作,同时保留重复项:

vecsets::vsetdiff( c(1,1,2,2,3,3,4,4), c(1) )
## [1] 1 2 2 3 3 4 4

vecsets::vsetdiff( c(1,1,2,2,3,3,4,4), c(1,1,2) )
## [1] 2 3 3 4 4

请注意,它将保留第一个参数的顺序。使用你的上一个例子:

vecsets::vsetdiff( c(3,4,3,1,2,2,1,4), c(1,1,2) )
## [1] 3 4 3 2 4

答案 1 :(得分:3)

this answer获取灵感,我在评论中链接了一个问题,您可以使用包中的all。 它需要setdiff作为参数,这样可以避免只返回唯一值,就像library(data.table) # with your first example (b = c(1)): unlist(fsetdiff(data.table(v1=a), data.table(v1=b), all = TRUE)) # v11 v12 v13 v14 v15 v16 v17 # 1 2 2 3 3 4 4 # with second example (b = c(1, 1, 2)): unlist(fsetdiff(data.table(v1=a), data.table(v1=b), all = TRUE)) # v11 v12 v13 v14 v15 # 2 3 3 4 4 一样:

mail.gimap.usesocketchannels

答案 2 :(得分:2)

您可以使用which()

a = c(3, 4, 3, 1, 2, 2, 1, 4)
a
## [1] 3 4 3 1 2 2 1 4

b = 1

a[- which(a %in% b)[1]]
## [1] 3 4 3 2 2 1 4

案例 b 有两个要素:

b2 = c(1, 2)

sapply(seq_along(b1), function(x) a <<- a[- which(a == x)[1]])[[2]]
## [1] 3 4 3 2 1 4

或者三......

b3 <- c(1, 2, 3)

sapply(seq_along(b1), function(x) a <<- a[- which(a == x)[1]])[[3]]
# [1] 4 3 2 1 4

答案 3 :(得分:0)

我不认为以下是最好的解决方案(vecsets方法让我觉得最好),但@Aaron关于可能使用Rcpp的评论让我感到有趣。这是我第一次使用该软件包。如果不出意外,我能够在不到20分钟内获得工作代码的事实强调了他的观点,即Rcpp让它相对容易:

library(Rcpp)
cppFunction('
  NumericVector difference(NumericVector xs, NumericVector ys){
    int m = xs.size();
    int n = ys.size();
    float flag = 1 + abs(max(xs)) + abs(max(ys)); //occurs in neither xs nor ys
    NumericVector zs = clone(xs);
    for(int i = 0; i < n; i++){
      double y = ys[i];
      int j = 0;
      while(j < m && zs[j]!= y) j++;
      if(j < m) zs[j] = flag;
    }
    int count = 0;
    for(int k = 0; k < m; k++){
      if(zs[k] < flag) count++;
    }
    NumericVector ws(count);
    int k = 0;
    for(int j = 0; j < m; j++){
      if(zs[j] < flag){
        ws[k] = zs[j];
        k++;
      }
    }
    return ws;
  }
')

您的来源:

> a = c(1,1,2,2,3,3,4,4)
> b = c(1,2,1)
> difference(a,b)
[1] 2 3 3 4 4

由于这是我第一次尝试这样的代码,我确信它可以通过多种方式进行改进。

答案 4 :(得分:0)

有点令人沮丧的是语法顺序,但是Reducewhich只用Base R来做。

Reduce(b, a) a[-which(a==b)[1]], a, b)