Вы можете выполнить построчное произведение Kronecker (из пакета MGLM
), как показано ниже
out <- data.frame(id = rep(df2$id,each=nrow(df1)),
t(MGLM::kr(t(df2[-1]),t(df1))))
, так что
> out
id intercept age male
1 a 3.4 3.20 0.07
2 a 3.6 2.00 0.06
3 a 3.7 2.40 0.07
4 b 3.4 3.60 0.00
5 b 3.6 2.25 0.00
6 b 3.7 2.70 0.00
Сравнительный анализ (пока что) подход @ Сотос является победителем)
df1 <- do.call(rbind,replicate(500,structure(list(intercept = c(3.4, 3.6, 3.7), age = c(0.08, 0.05,
0.06), male = c(0.07, 0.06, 0.07)), class = "data.frame", row.names = c(NA,
-3L)),simplify = F))
df2 <- do.call(rbind,replicate(100,structure(list(id = structure(1:2, .Label = c("a", "b"), class = "factor"),
intercept = c(1L, 1L), age = c(40L, 45L), male = 1:0), class = "data.frame", row.names = c(NA,
-2L)),simplify = F))
library(MGLM)
library(purrr)
f_ThomasIsCoding <- function() {
data.frame(id = rep(df2$id,each=nrow(df1)),
t(MGLM::kr(t(df2[-1]),t(df1))))
}
f_tmfmnk_1 <- function() {
map_dfr(.x = asplit(df2[-1], 1), ~ sweep(df1, 2, FUN = `*`, .x))
}
f_tmfmnk_2 <- function() {
data.frame(do.call(rbind, lapply(asplit(df2[-1], 1), function(x) sweep(df1, 2, FUN = `*`, x))),
id = rep(df2$id, each = nrow(df1)))
}
f_RonakShah <- function() {
new1 <- df1[rep(seq(nrow(df1)), nrow(df2)), ]
new2 <- df2[rep(seq(nrow(df2)), each = nrow(df1)),]
out <- cbind(new2[1], new1 * new2[-1])
rownames(out) <- NULL
out
}
f_Sotos <- function() {
data.frame(id = rep(df2$id, each = nrow(df1)),
mapply(function(x, y)c(outer(x, y, `*`)), df1, df2[-1])
)
}
bmk <- microbenchmark(times = 20,
unit = "relative",
f_ThomasIsCoding(),
f_tmfmnk_1(),
f_tmfmnk_2(),
f_RonakShah(),
f_Sotos())
, что дает
> bmk
Unit: relative
expr min lq mean median uq max neval
f_ThomasIsCoding() 1.186124 1.218201 1.197346 1.321731 1.042721 1.077854 20
f_tmfmnk_1() 7.594520 7.572723 4.539698 7.297610 2.437621 3.446436 20
f_tmfmnk_2() 9.670286 12.212220 6.583183 11.888061 3.370593 4.088534 20
f_RonakShah() 28.918724 28.861437 16.707258 27.889563 8.403161 11.668252 20
f_Sotos() 1.000000 1.000000 1.000000 1.000000 1.000000 1.000000 20