Мой быстрее.Он использует outer
вместо циклов, вот для чего он предназначен.
Сначала функции, которые не нуждаются во внешних пакетах, OP, один в комментарии user20650 и мой.
original <- function(u, v, x, y){
sum1 = 0
for (i in seq_along(u)){
for (j in seq_along(v)) {
sum1 = sum1 + (1 - max(u[i], v[j])) * (1 - max(x[i], y[j]))
}
}
sum1
}
comment <- function(u, v, x, y){
sum1 = 0
for (i in seq_along(u)){
sum1 = sum1 + (1 - pmax(u[i], v)) * (1 - pmax(x[i], y))
}
sum(sum1)
}
rui <- function(u, v, x, y){
tmp1 <- outer(u, v, pmax)
tmp2 <- outer(x, y, pmax)
sum((1 - tmp1) * (1 - tmp2))
}
Теперь функции в wwwответ и в ответ IceCreamToucan .
library(tidyverse)
www <- function(u, v, x, y){
dat <- data_frame(u, v, x, y)
dat2 <- dat %>% complete(nesting(u, x), nesting(v, y))
SUM2 <- sum(with(dat2, (1 - pmax(u, v)) * (1 - pmax(x, y))))
SUM2
}
IceCream <- function(u, v, x, y){
uv <- expand.grid(u, v)
xy <- expand.grid(x, y)
sum((1 - do.call(pmax, uv))*(1 - do.call(pmax, xy)))
}
Проверьте их все, чтобы увидеть, совпадают ли результаты.Обратите внимание, что существуют проблемы с плавающей запятой.
set.seed(1234)
u <- rnorm(1e2, 1)
v <- rnorm(1e2, 2)
x <- rnorm(1e2, 3)
y <- rnorm(1e2, 4)
o <- original(u, v, x, y)
c <- comment(u, v, x, y)
w <- www(u, v, x, y)
i <- IceCream(u, v, x, y)
r <- rui(u, v, x, y)
all.equal(o, c)
all.equal(o, w)
all.equal(o, i)
all.equal(o, r)
o - c
o - w
o - r
w - r
i - r
c - r
Теперь тест скорости.
library(microbenchmark)
library(ggplot2)
mb <- microbenchmark(
loop = original(u, v, x, y),
pmax = comment(u, v, x, y),
tidy = www(u, v, x, y),
ice = IceCream(u, v, x, y),
outer = rui(u, v, x, y)
)
autoplot(mb)