比较两个向量(包括多个项目)

时间:2018-02-22 10:52:02

标签: r

我需要找到新向量(vb)中的哪些元素已添加到另一个向量(va)中。例如,如果有一个" 2"在va,但是两个" 2"在vb中,然后是一个" 2"已被添加。

以下代码中的评论显示了所寻求的内容。

va <- c(1, 2)  # Original vector
vb <- c(1, 2)  # NA or NULL
vb <- c(2, 2)  # 2
vb <- c(1, 1)  # 1
vb <- c(1)     # NA or NULL
vb <- c(2)     # NA or NULL
vb <- c(3, 3)  # c(3, 3)

我已尝试过匹配,联合,交叉,%in%等等,但无法让它考虑多个实例。这感觉非常简单......

2 个答案:

答案 0 :(得分:2)

以下内容将再现您的预期结果。就像一个诚实的单挑,我对我的解决方案并不满意,这看起来很奇怪:

f <- function(a, b) {
    a <- as.data.frame(unclass(rle(a)));
    b <- as.data.frame(unclass(rle(b)));
    t <- merge(a, b, by = "values", all = TRUE);
    t$lengths.x[is.na(t$lengths.x)] <- 0;
    t$diff <- t$lengths.y - t$lengths.x;
    t <- t[!is.na(t$diff) & t$diff > 0, ];
    return(rep(t$values, t$diff));
}

va <- c(1, 2);
vb <- c(1, 2)  # NA or NULL
f(va, vb);
#numeric(0)

vb <- c(2, 2)  # 2
f(va, vb);
#[1] 2

vb <- c(1, 1)  # 1
f(va, vb);
#[1] 1

vb <- c(1)     # NA or NULL
f(va, vb);
#numeric(0)

vb <- c(2)     # NA or NULL
f(va, vb);
#numeric(0)

vb <- c(3, 3)  # c(3, 3)
#[1] 3 3

说明:我正在使用rle来比较vavb中不同条目的长度(重复级别);然后仅报告那些尚未在va中的人。

更新

这是一个使用递归函数的更简洁的方法。

f <- function(a, b) {
    if (length(a) == 0 | length(b) == 0) return(NULL);
    m <- data.frame(idx.a = 1:length(a), idx.b = match(a, b));
    m <- m[complete.cases(m), ];
    # Here is the recursive call
    if (nrow(m) > 0) f(a[-m$idx.a[1]], b[-m$idx.b[1]]) else b;
}

va <- c(1, 2)  # Original vector


f(va, c(1, 2));
#NULL

f(va, c(2, 2));
#[1] 2

f(va, c(1, 1));
#[1] 1

f(va, c(1));
#NULL

f(va, c(2));
#NULL

f(va, c(3, 3));
#[1] 3 3

答案 1 :(得分:1)

不是最优雅的,但它适用于所有情况:

Diff_frequency <- function(va,vb){
  df <- merge(as.data.frame(table(va)), as.data.frame(table(vb)), by.x="va", by.y="vb", all=T)
  df$Freq.x[is.na(df$Freq.x)] <- 0
  df$Dif <- df$Freq.y - df$Freq.x
  df$Dif[is.na(df$Dif) | df$Dif < 0] <- 0
  return(rep(as.numeric(as.character(df[,1])), df$Dif))
}

Diff_frequency(va,vb)

输出示例:

va=c(1,1,1,2,2,2,3)
vb=c(1,1,4,4,2,2,5)
Diff_frequency(va,vb)

[1] 4 4 5

va=c(1,1,1,2,2,2,3)
vb=c(1,1,1,1,2,2,2,3,3,5)
Diff_frequency(va,vb)

1] 1 3 5

va=c(1,1,1,2,2,2,3)
vb=c(1,1,2,3)
Diff_frequency(va,vb)

numeric(0)