Вот вариант использования data.table
с использованием скользящего соединения:
library(data.table)
A <- data.table(a, key="a")
B <- data.table(b, key="b")
A[, c("N", "cs") := .(.I, cumsum(a))]
A[B, on=.(a=b), roll=Inf, N * b - cs]
sum a[a <= n]
можно заменить на cumsum (т.е. cs
здесь), и скользящее соединение найдет те a
, которые менее b
. Замените sum(n - cs)
математической формулой, содержащей символ суммирования, чтобы sum(constant)
= количество элементов в суммировании * константа.
вывод:
[1] 0.0 2.5 9.0 19.5 34.0 52.5 75.0 101.5 132.0 166.5
изменить: некоторые тайминги для справки
код времени:
set.seed(0L)
library(data.table)
n <- 1e5L
a <- rnorm(n)
b <- rnorm(n/10L)
A <- data.table(a, key="a")
B <- data.table(b, key="b")
mtd0 <- function() A[B, on = .(a <= b), sum(i.b - x.a), by = .EACHI]$V1
mtd1 <- function() {
A[, c("N", "cs") := .(.I, cumsum(a))]
A[B, on=.(a=b), roll=Inf, N * b - cs]
}
all.equal(mtd0(), mtd1())
#[1] TRUE
microbenchmark::microbenchmark(times=1L, mtd0(), mtd1())
время:
Unit: milliseconds
expr min lq mean median uq max neval
mtd0() 2998.208000 2998.208000 2998.208000 2998.208000 2998.208000 2998.208000 1
mtd1() 7.807637 7.807637 7.807637 7.807637 7.807637 7.807637 1