R 中以下双 for 循环的有效实现是什么?
set.seed(1)
u <- rnorm(100, 1)
v <- rnorm(100, 2)
x <- rnorm(100, 3)
y <- rnorm(100, 4)
sum = 0
for (i in 1:100){
for (j in 1:100) {
sum = sum + (1 - max(u[i], v[j])) * (1 - max(x[i], y[j]))
}
}
特别是对于非常长的向量,评估需要相当长的时间,但我想知道是否有办法向量化这个双 for 循环?非常感谢。
最佳答案
我的速度更快。它使用 outer
而不是循环,这就是它的意思。
首先是不需要外部包的函数,OP,user20650's comment 中的函数和我的。
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's answer 中的函数在IceCreamToucan's answer .
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)
关于r - 具有最大操作的高效双 for 循环,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53694050/