具有重复值的两个向量之间的“设置差异”

use*_*195 6 r

我有 3 个向量

x <- c(1,3,5,7,3,8)
y <- c(3,5,7)
z <- c(3,3,8)
Run Code Online (Sandbox Code Playgroud)

我想找到x不在y和不在的元素z。是否有一个函数f可以给我以下输出:

> f(x,y)
1 3 8
> f(x,z)
1 5 7
Run Code Online (Sandbox Code Playgroud)

换句话说,我想找到两个向量之间的“集合差”,其中任何一个向量都可能有重复的值。该功能%in%match并且setdiff不要在此情况下,显而易见的原因工作。

Ron*_*hah 5

应该有一些更好的方法来做到这一点,但这是一种选择

get_diff_vectors <- function(x, y) {
  count_x <- table(x)
  count_y <- table(y)
  same_counts <- match(names(count_y), names(count_x))
  count_x[same_counts] <- count_x[same_counts] - count_y
  as.numeric(rep(names(count_x), count_x))
}

get_diff_vectors(x, y)
#[1] 1 3 8
get_diff_vectors(x, z)
#[1] 1 5 7
get_diff_vectors(x, c(5, 7))
#[1] 1 3 3 8
Run Code Online (Sandbox Code Playgroud)

我们指望的频率xy使用tablematch发生在两个和减计数的数字yx。最后使用 重新创建剩余的向量rep


仍然无法找到更好的方法,但这里是dplyr使用有些相似的逻辑的方法。

library(dplyr)

get_diff_vectors_dplyr <- function(x, y) {
  df1 <- data.frame(x) %>% count(x)
  df2 <- data.frame(y) %>% count(y)
  final <- left_join(df1, df2, by = c("x" = "y")) %>%
           mutate_at(c("n.x", "n.y"), funs(replace(., is.na(.), 0))) %>%
           mutate(n = n.x - n.y)

  rep(final$x, final$n)
}

get_diff_vectors_dplyr(x, y)
#[1] 1 3 8
get_diff_vectors_dplyr(x, z)
#[1] 1 5 7
get_diff_vectors_dplyr(x, c(5, 7))
#[1] 1 3 3 8
Run Code Online (Sandbox Code Playgroud)

vecsetsOP提到的包具有vsetdiff很容易做到这一点的功能

vecsets::vsetdiff(x, y)
#[1] 1 3 8
vecsets::vsetdiff(x, z)
#[1] 1 5 7
vecsets::vsetdiff(x, c(5, 7))
#[1] 1 3 3 8
Run Code Online (Sandbox Code Playgroud)

  • 这是一个很好的解决方案,谢谢,但我找到了一个包`vecsets`,它完全符合我的要求。不过我会接受这个答案。 (2认同)

the*_*ail 5

make.unique这是一个用于解释重复项的尝试:

dupdiff <- function(x,y) x[-match(
  make.unique(as.character(y)),
  make.unique(as.character(x)),
  nomatch=0
)]
Run Code Online (Sandbox Code Playgroud)

测试:

dupdiff(x,y)
#[1] 1 3 8
dupdiff(x,z)
#[1] 1 5 7
dupdiff(x, c(5, 7))
#[1] 1 3 3 8
dupdiff(x, c(5, 7, 9))
#[1] 1 3 3 8
Run Code Online (Sandbox Code Playgroud)