我是R
的初学者,正在探索可用于在向量中找到匹配元素(位置和布尔值)的不同选项。我有几个选项要做,我想看看每个的执行时间。令我惊讶的是,尽管他们做了同样的事情,但他们花了不同的时间。
有人可以对差异有所了解。
下面是查找匹配元素索引的脚本。尽管match
只找到了第一个索引,但which
花费的时间更短。
> obj<-c('a','b','c','d')
>
> system.time( replicate(10000, match('c',obj) ) )
user system elapsed
0.04 0.00 0.05
> system.time( replicate(10000, which('c'==obj) ) )
user system elapsed
0.04 0.00 0.03
对于返回布尔值,时间也不同。
> system.time( replicate(10000, is.element('c',obj) ) )
user system elapsed
0.05 0.00 0.05
> system.time( replicate(10000, 'c' %in% obj) )
user system elapsed
0.04 0.00 0.05
> system.time( replicate(10000, any('c'==obj) ) )
user system elapsed
0.02 0.00 0.02
非常感谢任何光明。
答案 0 :(得分:8)
match
需要构建一个哈希表,这是一项代价高昂的操作,只有在许多元素中搜索匹配时才有价值。 %in%
是match
的包装器。
which(x == y)
在向量上循环两次(一个用于测试相等性,一个用于返回TRUE
的索引。any(x == y)
的行为类似于which
但停止循环一次找到TRUE
。
match
仅返回第一个匹配,which
返回所有匹配。
您可以比较搜索匹配项的元素数量的性能,例如:
n = seq_len(1e2)
tab = seq_len(1e5)
ans = lapply(n, function(n) {
x = seq_len(n)
summary(microbenchmark::microbenchmark(match = match(x, tab),
which = unlist(lapply(x, function(X) which(X == tab))),
'in' = x %in% tab,
any = unlist(lapply(x, function(X)any(X == tab))),
unit = "ms",
times = 15))$median
})
plot(NULL, xlim = c(1, length(ans)), ylim = range(unlist(ans)))
lines(sapply(ans, "[[", 1), col = "red")
lines(sapply(ans, "[[", 2), col = "blue")
lines(sapply(ans, "[[", 3), col = "pink")
lines(sapply(ans, "[[", 4), col = "lightblue")
legend("topleft", fill = c("red", "blue", "pink", "lightblue"), legend = c("match", "which", "in", "any"))
编辑 2016年5月4日:
在R&gt; = 3.3.0中,当x
中的match(x, table)
为length(x) == 1L
时,会进行简单的线性搜索,直到找到第一个匹配项并且{{{}}开销为match
。 1}}的设置是避免的:
答案 1 :(得分:1)
我认为这些功能在效率上有所不同的原因并没有“明确”的答案。通常,提供相同输出的两个功能不需要同样有效。另一方面,可观察到的效率差异通常取决于输入(大小,格式)和使用函数的方式。
在您的示例中,is.element
和%in%
实际上是相同的,因为他们只是简单地调用match
来完成他们的工作。请参阅?is.element
和?match
以获取说明,并is.element
(R控制台中没有括号)了解该功能的用途。
第三个函数(any
)是一个原始函数。这些函数通常非常有效,因为它们直接执行C例程。处理原始函数的方式与R中的“常规”函数不同。
答案 2 :(得分:1)
您可以使用microbenchmark并查看哪一个更有效:
library(microbenchmark)
microbenchmark(match('c',obj),which('c'==obj),is.element('c',obj) , 'c' %in% obj,any('c'==obj),times =10000)
Unit: nanoseconds
expr min lq mean median uq max neval cld
match("c", obj) 489 978 1126.1920 979 980 1209606 10000 b
which("c" == obj) 489 978 1036.7159 979 980 31770 10000 b
is.element("c", obj) 978 1467 1810.8117 1468 1956 1150469 10000 c
"c" %in% obj 978 1468 1826.2425 1469 1957 27860 10000 c
any("c" == obj) 0 2 355.7135 490 491 23461 10000 a
microbenchmark(match('c',obj),which('c'==obj),is.element('c',obj) , 'c' %in% obj,any('c'==obj),times =1000000)
Unit: nanoseconds
expr min lq mean median uq max neval cld
match("c", obj) 489 978 995.9749 979 980 4391720 1e+06 b
which("c" == obj) 489 978 1013.2343 979 980 1193478 1e+06 b
is.element("c", obj) 978 1467 1663.1172 1468 1956 1202763 1e+06 c
"c" %in% obj 978 1468 1869.0499 1469 1957 56815228 1e+06 d
any("c" == obj) 0 2 348.8258 490 491 1186147 1e+06 a