15

给定一个a包含长度不等的向量的列表和一个b包含来自向量中的一些元素的向量a,我想获得一个长度相等的向量,以包含与 in中的元素匹配b的索引(我知道这是一个不好的解释)...ab

以下代码完成了这项工作:

a <- list(1:3, 4:5, 6:9)
b <- c(2, 3, 5, 8)

sapply(b, function(x, list) which(unlist(lapply(list, function(y, z) z %in% y, z=x))), list=a)
[1] 1 1 2 3

用 for 循环替换sapply当然可以达到同样的效果

问题是这段代码将与长度超过 1000 的列表和向量一起使用。在现实生活中,该函数大约需要 15 秒(for 循环和sapply)。

有谁知道如何加快速度,对并行方法安全吗?我没有看到矢量化方法(我不能用 C 编程,尽管这可能是最快的)。

编辑:

将只强调 Aaron 使用 match() 的优雅解决方案,它使速度提高了 1667 倍(从 15 到 0.009)

我对其进行了扩展以允许多个匹配项(然后返回一个列表)

a <- list(1:3, 3:5, 3:7)
b <- c(3, 5)
g <- rep(seq_along(a), sapply(a, length))
sapply(b, function(x) g[which(unlist(a) %in% x)])
[[1]]
[1] 1 2 3

[[2]]
[1] 2 3

运行时间为 0.169,可以说是相当慢,但另一方面更灵活

4

2 回答 2

16

这是使用的一种可能性match

> a <- list(1:3, 4:5, 6:9)
> b <- c(2, 3, 5, 8)
> g <- rep(seq_along(a), sapply(a, length))
> g[match(b, unlist(a))]
[1] 1 1 2 3

findInterval是另一种选择:

> findInterval(match(b, unlist(a)), cumsum(c(0,sapply(a, length)))+1)
[1] 1 1 2 3

要返回列表,请尝试以下操作:

a <- list(1:3, 4:5, 5:9)
b <- c(2,3,5,8,5)
g <- rep(seq_along(a), sapply(a, length))
aa <- unlist(a)
au <- unique(aa)
af <- factor(aa, levels=au)
gg <- split(g, af)
gg[match(b, au)]
于 2012-06-12T18:18:42.110 回答
0

正如对您的帖子的评论所暗示的那样,这取决于如果/当相同元素出现在a. 假设你想要你可以做的最低索引:

apply(sapply(a, function(vec) {b %in% vec}), 1, which.max)
于 2012-06-12T19:36:32.607 回答