我有 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不要在此情况下,显而易见的原因工作。
应该有一些更好的方法来做到这一点,但这是一种选择
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)
我们指望的频率x和y使用table,match发生在两个和减计数的数字y从x。最后使用 重新创建剩余的向量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)
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)