查找一个向量中小于另一个向量中的元素的元素数

kev*_*kuo 4 sorting r vector ranking time-complexity

假设我们有几个向量

a <- c(1, 2, 2, 4, 7)
b <- c(1, 2, 3, 5, 7)
Run Code Online (Sandbox Code Playgroud)

对于我想要的每个元素b[i],b找到的元素数量a少于b[i]或等价,我想知道b_i的等级c(b[i], a).

我可以想到几种天真的方式,例如,做以下任何一种情况length(b):

min_rank(c(b[i], a))
sum(a < b[i])
Run Code Online (Sandbox Code Playgroud)

如果length(a)= length(b)= N,其中N很大,那么最好的方法是什么?

编辑:

为了澄清,我想知道是否有一种计算效率更高的方法来做到这一点,即在这种情况下我是否能比二次时间更好.

矢量化总是很酷;),谢谢@Henrik!

运行时间

a <- rpois(100000, 20)
b <- rpois(100000, 10)

system.time(
  result1 <- sapply(b, function(x) sum(a < x))
)
# user  system elapsed 
# 71.15    0.00   71.16

sw <- proc.time()
  bu <- sort(unique(b))
  ab <- sort(c(a, bu))
  ind <- match(bu, ab)
  nbelow <- ind - 1:length(bu)
  result2 <- sapply(b, function(x) nbelow[match(x, bu)])
proc.time() - sw

# user  system elapsed 
# 0.46    0.00    0.48 

sw <- proc.time()
  a1 <- sort(a)
  result3 <- findInterval(b - sqrt(.Machine$double.eps), a1)
proc.time() - sw

# user  system elapsed 
# 0.00    0.00    0.03 

identical(result1, result2) && identical(result2, result3)
# [1] TRUE
Run Code Online (Sandbox Code Playgroud)

Blu*_*ter 5

假设a越来越弱,请使用findInterval:

a <- sort(a)
## gives points less than or equal to b[i]
findInterval(b, a)
# [1] 1 3 3 4 5
## to do strictly less than, subtract a small bit from b
## uses .Machine$double.eps (the smallest distinguishable difference)
findInterval(b - sqrt(.Machine$double.eps), a)
# [1] 0 1 3 4 4
Run Code Online (Sandbox Code Playgroud)


Gav*_*lly 5

如果您确实针对大 N 优化此过程,那么您可能希望至少在最初删除重复值b,然后可以排序和匹配:

bu <- sort(unique(b))
ab <- sort(c(a, bu))
ind <- match(bu, ab)
nbelow <- ind - 1:length(bu)
Run Code Online (Sandbox Code Playgroud)

由于我们将 a 和 b 值合并到 ab 中,因此match包含了所有小于 b 特定值的 a 以及所有 b 的值,因此这就是我们在最后一行删除 b 的累计计数的原因。我怀疑这对于大型集合可能会更快 - 如果match对排序列表进行内部优化,则应该是这样,希望是这种情况。然后映射回你原来的snbelow集应该是一件小事b