这里是发布的for 循环的 3 个不同版本。
-
f1:从循环中移除条件;
-
f2:预计算差异B - A;
-
f3:预先计算差异B - A,将它们与start_value 作为第一个元素和cumsum 滞后。
第 3 个函数 f3 比原来快 6 倍。
f0 <- function(df, start_value){
for(i in seq_along(df[,1])){
if (i==1){
df[i,"C"]=start_value- df[i,"A"]+df[i,"B"]
}else{
df[i,"C"]=df[i-1,"C"]- df[i,"A"]+df[i,"B"]
}
}
df
}
f1 <- function(df, start_value){
df[1, "C"] <- start_value - df[1, "A"] + df[1, "B"]
for(i in seq_len(nrow(df))[-1]){
df[i, "C"] <- df[i - 1, "C"] - df[i, "A"] + df[i, "B"]
}
df
}
f2 <- function(df, start_value){
tmp <- as.vector(as.matrix(df[c("A", "B")]) %*% c(-1, 1))
df[1, "C"] <- start_value + tmp[1]
for(i in seq_len(nrow(df))[-1]){
df[i, "C"] <- df[i - 1, "C"] + tmp[i]
}
df
}
f3 <- function(df, start_value){
tmp <- as.vector(as.matrix(df[c("A", "B")]) %*% c(-1, 1))
y <- c(start_value + tmp[1], tmp[-1])
df[["C"]] <- cumsum(y)
df
}
start_value <- 4
df <- data.frame(A=1:10, B=2:11, C=NA)
x0 <- f0(df, 4)
x1 <- f1(df, 4)
x2 <- f2(df, 4)
x3 <- f3(df, 4)
identical(x0, x1) # TRUE
identical(x0, x2) # TRUE
identical(x0, x3) # TRUE
library(microbenchmark)
mb <- microbenchmark(
f0 = f0(df, 4),
f1 = f1(df, 4),
f2 = f2(df, 4),
f3 = f3(df, 4)
)
print(mb, order = "median")
#Unit: microseconds
# expr min lq mean median uq max neval cld
# f3 223.560 234.1325 456.6144 253.780 299.273 19289.107 100 a
# f2 962.414 1372.4640 1417.5630 1394.816 1457.883 1899.316 100 b
# f1 1561.998 1916.0750 1962.7880 1938.282 1980.583 2379.496 100 c
# f0 1229.716 1932.5730 1969.8554 1957.974 1992.095 3161.792 100 c