The goal of havel is to vizualize and tabulate dependencies in R packages. This will help R package developers identify dependencies that contribute more to the dependency load and/or are easier to remove.
You can install the development version of havel from GitHub with:
# install.packages("pak")
pak::pak("andrewGhazi/havel")Once available on CRAN, install like so:
install.packages("havel")havel has two main functions:
plot_deps_graph() and uniq_pkg_deps().
plot_deps_graph()Use plot_deps_graph() to look up and plot the dependency
graph of a package:
library(havel)
plot_deps_graph("ggplot2")
You can see that:
ggplot2 has 21 dependencies in total (direct and
indirect).scales package contributes several
dependencies that nothing else depends on. If the ggplot2
developers were looking to lighten their package (not that they should),
eliminating the dependency on scales might be a good place
to start looking.Another example: What if I wanted to remove Rcpp as a
dependency of havel itself?
plot_deps_graph("andrewGhazi/havel") # looks it up on GitHub
Well, looks like that would be difficult. Even if I removed the
direct dependency, there would still be an indirect dependency on
Rcpp through collapse and
cppRouting. I would need to remove all three to avoid
dependence on Rcpp.
uniq_pkg_deps()uniq_pkg_deps() tabulates what’s visually apparent on
the plot:
uniq_pkg_deps("ggplot2")
#> p1 n_uniq uniq_pkgs
#> <char> <num> <list>
#> 1: scales 6 viridisLite,labeling,R6,farver,RColorBrewer
#> 2: cli 1
#> 3: grDevices 1
#> 4: grid 1
#> 5: gtable 1
#> 6: isoband 1
#> 7: lifecycle 1
#> 8: rlang 1
#> 9: S7 1
#> 10: stats 1
#> 11: vctrs 1
#> 12: withr 1scales introduces six unique dependencies to
ggplot2, including itself.
Sometimes there’s no single package that introduces many unique
dependencies, but there may be a pair or triplet that
does. You can check the impact of removing each combination of
order = 2 packages like so:
uniq_pkg_deps("ggplot2", order = 2) |>
head()
#> p1 p2 n_uniq uniq_pkgs
#> <char> <char> <num> <list>
#> 1: scales withr 8 viridisLite,labeling,graphics,R6,farver,RColorBrewer
#> 2: cli scales 7 viridisLite,labeling,R6,farver,RColorBrewer
#> 3: grDevices scales 7 viridisLite,labeling,R6,farver,RColorBrewer
#> 4: grid scales 7 viridisLite,labeling,R6,farver,RColorBrewer
#> 5: gtable scales 7 viridisLite,labeling,R6,farver,RColorBrewer
#> 6: isoband scales 7 viridisLite,labeling,R6,farver,RColorBrewerscales + withr introduce eight.
There are other packages / posts out there on this type of thing:
miniCRAN
has a vignette on similar plotting functionality: “Using miniCRAN to
identify package dependencies”.pkgnet
offers an expansive dependency analysis suite.depgraph
(on GitHub only, not CRAN) is pretty similar but uses different
aesthetic mappings.DependenciesGraphs
and pkgdepR
visualize the dependencies of functions used within a
package.pkgndep
visualizes similar information in a heatmap format, as well as provides
different “heaviness” metrics.havel offers some unique advantages nonetheless:
pak::pkg_deps() to look up the dependency
connections instead of tools::package_dependencies(). This
enables more versatile lookups of packages on Bioc, GitHub, etc.havel itself is fairly light and fast, depending only
on pak, some fastverse packages, and base R graphics…
gg = TRUE.Why’d you make this?
What’s with the name?
Havel’s Ring is an item in Dark Souls that helps you deal with excessive burdens. (Plus, every permutation of “pkg”/“dep”/“graph” was taken.)
methods →
utils,stats)info_method = "tools"