我想在另一个查找向量table
中找到向量x
的所有匹配的索引。
table = rep(1:5, each=3)
x = c(2, 5, 2, 6)
字符串
标准的R基方法并不能完全给予我想要的东西,例如使用which(table %in% x)
我们只能得到一次匹配的索引,即使2
在x
中出现了两次
which(table %in% x)
# [1] 4 5 6 13 14 15
型
另一方面,match
返回每个匹配x的值,但只返回查找表中的第一个索引。
match(x, table)
# [1] 4 13 4 NA
型
我想要的是一个函数,返回“所有x和所有y”的索引。即。它应该返回以下所需的结果:
mymatch(x, table)
# c(4, 5, 6, 13, 14, 15, 4, 5, 6)
型
当然,我们可以用R中的循环来做到这一点:
mymatch = function(x, table) {
matches = sapply(x, \(xx) which(table %in% xx))
unlist(matches)
}
mymatch(x, table)
# [1] 4 5 6 13 14 15 4 5 6
型
但这在大数据上非常慢(我需要在大数据上多次执行此操作)
table = rep(1:1e5, each=10)
x = sample(1:100, 1000, replace = TRUE)
system.time(mymatch(x, table))
# user system elapsed
# 3.279 2.881 6.157
型
如果我们将其与which %in%
进行比较,这是非常慢的:
system.time(which(table %in% x))
# user system elapsed
# 0.003 0.004 0.008
型
希望有一个快速的方法在R中做到这一点?否则,也许RCpp是要走的路。
6条答案
按热度按时间ruoxqz4g1#
另一种方法是使用
split
:字符串
编辑:
注意,如果
table
是排序的,那么你可以使用rle + sequence
:型
只要表被排序,该函数就可以工作。不一定从1:n开始。
型
gab6jxml2#
也许data.table会是一个选择?如果你有相对较大的table/vector,你可能会看到速度的提高,特别是如果你使用Jon Spring的“join”方法的沿着:
字符串
x1c 0d1x的数据
创建于2023-10-26带有reprex v2.0.2
tpgth1q73#
作为连接应该更快。这是> 100倍的速度。
字符串
同样的输出,100- 200倍的速度,和来自@Onyambu的基本R建议一样快~ 3倍(注意:这种方法已经更新到类似的速度,而data.table解决方案甚至更快。使用duckdb,或箭头,或折叠来做连接可能会更快。但我的观察仍然是,你可以通过将其视为连接来获得显着的速度改进+易读性):
型
huus2vyu4#
使用问题中的数据,这是基于我机器上的中值时间的两倍。
字符串
pbpqsu0x5#
您可以简单地运行
outer
+row
(简短的代码,但由于outer
的原因,可能不是那么有效),例如,字符串
au9on6nz6#
如果被匹配的值是整数,那么你可以将它们作为一个包含你想要的索引值的列表中的索引值(只要最大整数不是太大,以至于列表超过了你的RAM容量)。
字符串
现在,这并不像这里提到的其他解决方案那么快,但是因为你要重用表进行多次查找,我们可以预先计算列表的创建并在迭代中重用它:
型
事实证明,列表查找和取消列表部分非常便宜:
的数据
所以,这取决于重复使用相同的表向量多少次来弥补初始设置。就内存使用而言,我认为查找和取消列表也应该相当有效(查找基本上什么都没有,取消列表与
x
向量的大小有关),但我还没有尝试过分析它们。