Skip to content

Commit eb1e946

Browse files
committed
added manual test for speed of simulatedce
1 parent 1e7ad2d commit eb1e946

File tree

1 file changed

+92
-0
lines changed

1 file changed

+92
-0
lines changed
Lines changed: 92 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,92 @@
1+
# ─────────────────────────────────────────────────────────────────────────────
2+
# BENCHMARK: add NEW3 using dt[, .. := .., by=group]
3+
# ─────────────────────────────────────────────────────────────────────────────
4+
5+
library(formula.tools); library(compiler)
6+
library(dplyr); library(purrr)
7+
library(data.table); library(tictoc)
8+
9+
# 1) Prepare data ------------------------------------------------------------
10+
set.seed(2025)
11+
n <- 1e7
12+
ngrp <- 10
13+
df <- data.frame(
14+
price = runif(n, 5, 100),
15+
quality = runif(n, 1, 5),
16+
group = rep(1:ngrp, length.out = n)
17+
)
18+
bprice <- -0.2; bquality <- 0.8
19+
single_group <- list(
20+
V1 = V1 ~ bprice * price + bquality * quality,
21+
V2 = V2 ~ 0
22+
)
23+
utility_list <- rep(list(single_group), ngrp)
24+
25+
# 2) Helpers ---------------------------------------------------------------
26+
by_formula <- function(eq) pick(everything()) %>% transmute(!!lhs(eq) := !!rhs(eq))
27+
compile_one <- function(fm){
28+
nm <- as.character(lhs(fm)); rhs <- rhs(fm)
29+
fn <- eval(bquote(function(df) with(df, .(rhs))))
30+
list(name = nm, fun = cmpfun(fn))
31+
}
32+
compile_utility_list <- function(u) lapply(u, function(fl){
33+
tmp <- lapply(fl, compile_one)
34+
setNames(lapply(tmp, `[[`, "fun"),
35+
vapply(tmp, `[[`, "", "name"))
36+
})
37+
38+
# 3) Methods --------------------------------------------------------------
39+
40+
old_group <- function(data, utility) {
41+
tic("OLD-GROUP")
42+
subs <- split(data, data$group)
43+
subs2 <- map2(utility, subs, ~ mutate(.y, map_dfc(.x, by_formula)))
44+
out <- bind_rows(subs2)
45+
toc(log = FALSE)
46+
out
47+
}
48+
49+
new1_group <- function(data, utility) {
50+
ufuns <- compile_utility_list(utility)
51+
tic("NEW1-GROUP")
52+
subs <- split(data, data$group)
53+
subs2 <- map2(ufuns, subs, ~ bind_cols(.y, lapply(.x, function(f) f(.y))))
54+
out <- bind_rows(subs2)
55+
toc(log = FALSE)
56+
out
57+
}
58+
59+
new2_group <- function(data, utility) {
60+
ufuns <- compile_utility_list(utility)
61+
dt <- setDT(data)
62+
tic("NEW2-GROUP (loop)")
63+
for (g in seq_along(ufuns)) {
64+
fns <- ufuns[[g]]
65+
dt[group == g, (names(fns)) := lapply(fns, function(f) f(.SD))]
66+
}
67+
toc(log = FALSE)
68+
as.data.frame(dt)
69+
}
70+
71+
new3_group <- function(data, utility) {
72+
ufuns <- compile_utility_list(utility)
73+
dt <- setDT(data)
74+
varnames <- names(ufuns[[1]])
75+
tic("NEW3-GROUP (by=group)")
76+
dt[, (varnames) := lapply(ufuns[[.BY$group]], function(f) f(.SD)), by = group]
77+
toc(log = FALSE)
78+
as.data.frame(dt)
79+
}
80+
81+
# 4) Run & validate ---------------------------------------------------------
82+
res_old <- old_group(df, utility_list)
83+
res_new1 <- new1_group(df, utility_list)
84+
res_new2 <- new2_group(df, utility_list)
85+
res_new3 <- new3_group(df, utility_list)
86+
87+
stopifnot(
88+
identical(res_old, res_new1),
89+
identical(res_new1, res_new2),
90+
identical(res_new2, res_new3)
91+
)
92+
message("✅ All four methods agree on results.")

0 commit comments

Comments
 (0)