在R中,我有一个元素x和一个向量v。我想在v中找到等于x的元素的第一个索引。我知道执行此操作的一种方法是:which(x == v)[[1]],但这似乎效率太低。有更直接的方法吗?

对于积分,如果x是向量,是否存在可以使用的函数?也就是说,它应该返回一个索引向量,指示x中每个元素在v中的位置。

评论

由于R已针对与矢量一起使用进行了优化,因此(x == v)[[1]]效率不是很高。这是一个应用于所有矢量元素的比较(==)运算符,并且是索引(其中)的一个子集。而已。只要您没有在此函数上运行10.000次重复,就没有关系了。其他解决方案(例如匹配和排名)可能不会返回那么多的数据,但不一定能提高效率。

我的问题指定我希望对x进行矢量化的函数,而对(x == v)[[1]]不是。

#1 楼

函数match适用于矢量:
x <- sample(1:10)
x
# [1]  4  5  9  3  8  1  6 10  7  2
match(c(4,8),x)
# [1] 1 5

match仅根据您的请求返回匹配的第一个匹配项。它返回第一个参数中值在第二个参数中的位置。
对于多重匹配,%in%是可行的方法:
x <- sample(1:4,10,replace=TRUE)
x
# [1] 3 4 3 3 2 3 1 1 2 2
which(x %in% c(2,4))
# [1]  2  5  9 10

%in%返回逻辑矢量,只要第一个参数,如果在第二个参数中可以找到该值,则使用TRUE,否则使用FALSE

评论


我认为具有c(2,3,3)和c(1,2,3,4)且具有match和%in%的示例将更具指导性,并且示例之间的更改较少。 match(c(2,3,3),c(1:4))返回不同的结果,其中which(c(2,3,3)%in%c(1:4))不需要更长的第一向量,并且实例之间有很多变化。还值得注意的是,它们对不匹配的处理方式非常不同。

–约翰
2011年4月7日13:30

@John:没错,但这不是OP要求的。 OP要求从一个长向量开始,查找另一个元素中给定的元素的第一个匹配项。为了完整起见,我补充说,如果您对所有索引都感兴趣,则必须使用which(%in%)。顺便说一句,没有理由删除您的答案。这是有效信息。

– Joris Meys
2011年4月7日13:36

我想强调一点,如果您想要第一次出现的索引,则匹配中参数的顺序很重要。对于您的示例,match(x,c(4,8))给出不同的结果,起初并不十分明显。

– apitsch
17年6月11日在9:20



@goldenoslik如果您阅读比赛的帮助页面,它将对您有帮助。一切都在那里解释。但是我添加了那条信息。

– Joris Meys
17年6月11日在10:14

#2 楼

funprog {base}中的函数Position也可以完成此工作。它允许您传递任意函数,并返回第一个或最后一个匹配项。

Position(f, x, right = FALSE, nomatch = NA_integer)

#3 楼

关于上述方法效率的一点说明:

 library(microbenchmark)

  microbenchmark(
    which("Feb" == month.abb)[[1]],
    which(month.abb %in% "Feb"))

  Unit: nanoseconds
   min     lq    mean median     uq  max neval
   891  979.0 1098.00   1031 1135.5 3693   100
   1052 1175.5 1339.74   1235 1390.0 7399  100


因此,最好的方法是

    which("Feb" == month.abb)[[1]]


评论


您的基准基于长度12向量,因此没有意义。同样在您的示例中,which(“ Feb” == month.abb)返回2 –为什么[[1]]吗?

–马库斯
19年11月20日在20:17

@markus此代码which(“ Feb” == month.abb)[[1]]返回“ 2”,并且此代码which(month.abb%in%“ Feb”)也返回“ 2”。另外,不清楚为什么使用向量没有意义

–安德里
19年11月21日在16:48

它与向量无关,而与向量的长度有关。您应该生成适当长度的向量,然后根据该向量进行基准测试。引用OP的问题“我知道实现此目的的一种方法是:which(x == v)[[1]],但这似乎效率太低。”

–马库斯
19年11月21日在22:05