I mean, it's possible, of course:
quick_summary <- function(df, vars, group){
do.call(rbind,
lapply(vars,
function(variable){
result <- aggregate(
as.formula(paste(variable, '~', paste(group, collapse = '+'))),
mtcars,
function(value){
c(n = sum(!is.na(value)),
mean = mean(value, na.rm = TRUE),
sd = sd(value, na.rm = TRUE),
min = min(value, na.rm = TRUE),
median = median(value, na.rm = TRUE),
max = max(value, na.rm = TRUE))
})
cbind(variable = variable,
result[-which(names(result) == variable)],
result[[variable]])
}
)
)
}
quick_summary(mtcars, c("mpg", "hp", "wt"), c("am", "gear"))
#> variable am gear n mean sd min median max
#> 1 mpg 0 3 15 16.10667 3.3716182 10.400 15.500 21.500
#> 2 mpg 0 4 4 21.05000 3.0697448 17.800 21.000 24.400
#> 3 mpg 1 4 8 26.27500 5.4144648 21.000 25.050 33.900
#> 4 mpg 1 5 5 21.38000 6.6589789 15.000 19.700 30.400
#> 5 hp 0 3 15 176.13333 47.6892720 97.000 180.000 245.000
#> 6 hp 0 4 4 100.75000 29.0100557 62.000 109.000 123.000
#> 7 hp 1 4 8 83.87500 24.1745882 52.000 79.500 110.000
#> 8 hp 1 5 5 195.60000 102.8338466 91.000 175.000 335.000
#> 9 wt 0 3 15 3.89260 0.8329929 2.465 3.730 5.424
#> 10 wt 0 4 4 3.30500 0.1567376 3.150 3.315 3.440
#> 11 wt 1 4 8 2.27250 0.4608145 1.615 2.260 2.875
#> 12 wt 1 5 5 2.63260 0.8189254 1.513 2.770 3.570
There are definitely some subtleties involved, though, and it's certainly way slower to write correctly than the tidyverse equivalent.
But I think Miles hits on the crux of the issue:
Making tidyverse a dependency of your package adds 47 packages via Depends/Imports, and more via Suggests. If the package extends the tidyverse framework (dplyr bindings for a database, say) or is for your own personal use, that's probably fine, as your users/you already have all those packages installed.
However, if you're writing a package you intend to be broadly used, keep in mind that you're making your package really heavy in terms of install time, space required, etc., and some users will avoid your package for that reason. On your own end, you'll see the difference if you add dplyr to your dependencies in your Travis/AppVeyor build times, which will shoot up by about half an hour.
Thus, my position is that if you intend a package for broad use and it's not inherently designed to only work with the tidyverse, it's worth it to put in the extra time to write it in base R. A different subset of base R functions like match.arg will become necessary anyway, so it's frequently not much more work to rewrite the rest. As much as I find the tidyverse indispensable for non-package code, I do my best to make the packages I work on grammar-agnostic when possible, even if it means getting comfortable with vapply.