如何找出一个集合中的元素是否在另一个集合中?

4

我有两个集合:A包含x,y两列,B也包含x,y两列。 我需要找到A中那些行的索引在B中也存在(x和y必须匹配)。 我想出了一个简单的解决方案(见下文),但是这个比较操作在循环内部,并且paste会增加更多的额外时间。

B <- data.frame(x = sample(1:1000, 1000), y = sample(1:1000, 1000))
A <- B[sample(1:1000, 10),]
#change some elements
A$x[c(1,3,7,10)] <- A$x[c(1,3,7,10)] + 0.5

A$xy <- paste(A$x, A$y, sep='ZZZ')
B$xy <- paste(B$x, B$y, sep='ZZZ')
indx <- which(A$xy %in% B$xy)
indx

例如,对于单个观察值,paste的替代方法快了近3倍。
    ind <- sample(1:1000, 1)
    xx <- B$x[ind]
    yy <- B$y[ind]

    ind <- which(with(B, x==xx & y==yy))
    # [1] 0.0160000324249268 seconds
    xy <- paste(xx,'ZZZ',yy, sep='')
    ind <- which(B$xy == xy)
    # [1] 0.0469999313354492 seconds

1
如果您所匹配的列是整数或字符类型的,那么data.table包可能会提供解决方案。对于许多匹配和索引类型操作,它比其他方法快得多。 - Josh O'Brien
1个回答

2
如何使用merge()来进行匹配?
A$id <- seq_len(nrow(A))
sort(merge(A, B)$id)
# [1] 2 4 5 6 8 9

编辑:

或者,为了避免两个不必要的排序,使用merge()sort=选项。

merge(A, B, sort=FALSE)$id
# [1] 2 4 5 6 8 9

1
@ilya 这样更好。你可能还可以做类似于 which(tail(duplicated(rbind(B,A)),nrow(A))) 的事情,但那可能会比较慢。 - joran
这个方法是可行的,但不幸的是没有节省时间。粘贴需要0.0309秒,而这种方法需要0.0469秒。我正在进行模拟项目。大约40分钟的真实时间花费了我24小时。我正在尝试提高性能。现在已经缩短到了9小时。通过分析,我发现这部分代码占用了很多时间,所以我正在寻找更快的替代方案。 - ilya
好的,可能仍然有时间节省。我不需要在 B 上进行粘贴。这可能会为我节省时间。我将进行更多测试。 - ilya
是的 - 如果你想追求速度,那么使用merge()可能会有一个副作用过度的问题。话虽如此,merge.data.frame()中的代码可能是一个很好的思路来源。它的作者可能曾经面对你现在正在面临的速度问题。请告诉我们你发现了什么! - Josh O'Brien
@CarlWitthoft -- 我同意。match() 例如,使用哈希表,但计算出的表不是持久的。如果你在同一个表中不断查找东西,你就会失去这个好处。 Chambers 在他的书中引用了这一点,在这段文字中提到,环境可能提供了解决方案。我希望我能更好地理解这一点。 - Josh O'Brien
显示剩余2条评论

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