t.test{roxygen} and tests with {testthat}#> # A tibble: 2 × 4
#> expression min median mem_alloc
#> <bch:expr> <bch:tm> <bch:tm> <bch:byt>
#> 1 mean1(x) 143.7µs 181.8µs 23.3KB
#> 2 mean2(x) 68.9µs 86.8µs 0B
{usethis} and {devtools} for developing and testing functions

usetihs::create_package()devtools::load_all() to load and use functionsAfter exhausting options at hand, online resources can provide new approaches not thought of.
Alternatively, reframe the problem to find solutions e.g. new paradigm
Talking to peers helps brainstorm solutions and reframe the problem
Learning broadly improves your ability to dissect problems and develop solutions
#> # A tibble: 2 × 4
#> expression min median mem_alloc
#> <bch:expr> <bch:tm> <bch:tm> <bch:byt>
#> 1 colMeans(X) 559.6µs 711.7µs 99.3KB
#> 2 apply(X, 2, function(x) sum(x)/length(x)) 15.1ms 17.3ms 12.6MB
vapply allocates less memory#> # A tibble: 2 × 4
#> expression min median mem_alloc
#> <bch:expr> <bch:tm> <bch:tm> <bch:byt>
#> 1 vapply(X, mean, numeric(1)) 498ms 500ms 78.2KB
#> 2 sapply(X, mean) 510ms 510ms 362.6KB
any is faster and allocates less memory than %in%random_string <- function() {
paste(sample(letters, 50, replace = TRUE), collapse = "")
}
strings10 <- replicate(10, random_string())
strings100 <- replicate(100, random_string())
collapse <- function(xs) {
out <- ""
for (x in xs) { out <- paste0(out, x) }
out
}
bench::mark(
loop10 = collapse(strings10),
loop100 = collapse(strings100),
vec10 = paste(strings10, collapse = ""),
vec100 = paste(strings100, collapse = ""),
check = FALSE
)[c("expression", "min", "median", "mem_alloc", "n_gc")]#> # A tibble: 4 × 4
#> expression min median mem_alloc
#> <bch:expr> <bch:tm> <bch:tm> <bch:byt>
#> 1 loop10 15.8µs 20.7µs 15.5KB
#> 2 loop100 438.1µs 530.1µs 251.5KB
#> 3 vec10 3µs 3.6µs 0B
#> 4 vec100 16.4µs 20µs 848B
t.testttest_malgebra <- function(x, groups) {
t_stat <- function(x) {
m <- mean(x); n <- length(x)
var <- sum((x - m) ^ 2) / (n - 1)
list(m = m, n = n, var = var)
}
purrr::map_dbl(
1:ncol(x),
function(i) {
g1 <- t_stat(x[groups == 1,i]); g2 <- t_stat(x[groups == 2,i])
se_total <- sqrt(g1$var / g1$n + g2$var / g2$n)
(g1$m - g2$m) / se_total
}
)
}ttest_vectorise <- function(x, groups) {
x1 <- x[groups == 1, , drop = FALSE]
x2 <- x[groups == 2, , drop = FALSE]
n1 <- nrow(x1)
n2 <- nrow(x2)
m1 <- Matrix::colMeans(x1)
m2 <- Matrix::colMeans(x2)
v1 <- Matrix::colSums(
(x1 - matrix(m1, n1, ncol(x), byrow = TRUE)
)^2) / (nrow(x1) - 1)
v2 <- Matrix::colSums(
(x2 - matrix(m2, n2, ncol(x), byrow = TRUE)
)^2) / (nrow(x2) - 1)
se_total <- sqrt(v1 / n1 + v2 / n2)
(m1 - m2) / se_total
}#> # A tibble: 5 × 4
#> expression min median mem_alloc
#> <bch:expr> <bch:tm> <bch:tm> <bch:byt>
#> 1 ttest_base(X, grp) 89.9ms 93ms 13.7MB
#> 2 ttest_nocopy(X, grp) 84ms 85.3ms 6.48MB
#> 3 ttest_nodispatch(X, grp) 76.4ms 76.7ms 5.82MB
#> 4 ttest_malgebra(X, grp) 10.8ms 13.6ms 4.02MB
#> 5 ttest_vectorise(X, grp) 490.8µs 785µs 99.38MB