I a have function that uses the data.table syntax. The function works but is way too slow.
I know there has to be a better way to do this. This is my function and some setup for reproducibility:
library(tidyverse)
library(data.table)
sw <- data.table(starwars)
# Large data-set to make difference noticeable
for (i in 1:15) {
sw <- rbind(sw, sw)
}
# My working but slow function
dt.fun <- function(expr) {
sw[, .("mean_bin" = mean(eval(parse(text = expr)),
na.rm = T)),
by = species]
}
The function takes an expression and calculates the mean of that expression within each species. The function must be able to take any expression that a regular user could type in the command window, i.e. it must be able to calculate all of the following:
dt.fun("height > 150")
dt.fun("hair_color %in% c('brown', 'blond')")
dt.fun("mass")
The problem is that my function takes too long and is clearly not leveraging data.table's power:
# Using dt.fun()
tictoc::tic()
dt.fun("height > 150")
tictoc::toc()
# 2.23 sec elapsed
# Inputting the expression myself
tictoc::tic()
sw[, .("mean_bin" = mean(height > 150, na.rm = T)),
by = species]
tictoc::toc()
# 0.28 sec elapsed
My questions are:
- How can I rewrite my function so that it's faster?
- What other improvements would you make?
Thanks for your help!