https://github.com/lewinfox/foodwebr
Function dependency graphs in R
https://github.com/lewinfox/foodwebr
code-tools function-dependency introspection r
Last synced: about 2 months ago
JSON representation
Function dependency graphs in R
- Host: GitHub
- URL: https://github.com/lewinfox/foodwebr
- Owner: lewinfox
- License: other
- Created: 2021-05-05T05:37:03.000Z (almost 5 years ago)
- Default Branch: main
- Last Pushed: 2025-10-01T00:53:00.000Z (5 months ago)
- Last Synced: 2025-10-01T02:43:44.829Z (5 months ago)
- Topics: code-tools, function-dependency, introspection, r
- Language: R
- Homepage: http://www.lewinfox.com/foodwebr/
- Size: 1.51 MB
- Stars: 30
- Watchers: 2
- Forks: 4
- Open Issues: 1
-
Metadata Files:
- Readme: README.Rmd
- Changelog: NEWS.md
- License: LICENSE
Awesome Lists containing this project
README
---
output: github_document
always_allow_html: true
---
```{r, include = FALSE}
knitr::opts_chunk$set(
collapse = TRUE,
comment = "#>",
fig.path = "man/figures/README-",
out.width = "100%",
fig.height = 2
)
```
```{r, include = FALSE}
if (!requireNamespace("cowsay", quietly = TRUE)) {
install.packages("cowsay")
}
```
# foodwebr
[](https://github.com/lewinfox/foodwebr/actions/workflows/R-CMD-check.yaml)
`foodwebr` makes it easy to visualise the dependency graph of a set of functions
(i.e. who calls who). This can be useful for exploring an unfamiliar codebase,
or reminding yourself what you wrote ten minutes ago
## Installation
You can install foodwebr from CRAN:
``` r
install.packages("foodwebr")
```
or from GitHub:
``` r
devtools::install_github("lewinfox/foodwebr")
```
## Basic usage
Say we have a bunch of functions in the global environment, some of which call
each other:
```{r setup}
library(foodwebr)
f <- function() 1
g <- function() f()
h <- function() { f(); g() }
i <- function() { f(); g(); h() }
j <- function() j()
```
A call to `foodweb()` will calculate a graph of the dependencies.
```{r foodweb-basic}
fw <- foodweb()
```
Printing the object will show the [graphviz](https://graphviz.org/)
representation:
```{r foodweb-print}
fw
```
Plotting will draw the graph.
```r
plot(fw)
```

`foodweb()` looks at its calling environment by default. If you want to look at
another environment you can either pass a function to the `FUN` argument of
`foodweb()` or pass an environment to the `env` argument. If `FUN` is provided
then the value of `env` is ignored, and the environment of `FUN` will be used.
### Filtering
If a specific function is passed to `FUN`, the default behaviour is to remove
functions that are not descendants or antecedents of that function.
```{r foodweb-filter}
# `j()` will not be included
foodweb(FUN = g)
# Force inclusion of unconnected functions by using `filter = FALSE`
foodweb(FUN = g, filter = FALSE)
```
You can use this feature when exploring code in other packages: calling
`foodweb()` on a function in another package will show you how functions in that
package relate to each other. I'm using `cowsay` here as it's small enough that
the output is readable.
By default when calling `foodweb()` on a specific function we only see functions
that are in the direct line of descendants or antecendents of the specified
function.
``` r
if (requireNamespace("cowsay", quietly = TRUE)) {
plot(foodweb(cowsay::say))
}
```

If we want to include _all_ functions in the package, we can pass
`filter = FALSE`:
```r
if (requireNamespace("cowsay", quietly = TRUE)) {
plot(foodweb(cowsay::say, filter = FALSE))
}
```

### Extra `graphviz` options
In case you want to do something with the [graphviz](https://graphviz.org/)
output (make it prettier, for example), you can pass additional arguments to
`plot()`. These will be passed directly to `DiagrammeR::grViz()`.
### Foodweb as text
```{r foodweb-as-text}
foodweb(as.text = TRUE)
```
Calling `as.character()` on a `foodweb` object will have the same effect.
## Using `tidygraph`
The [`tidygraph`](https://tidygraph.data-imaginist.com/) package provides tools
for graph analysis. A `foodweb` object can be converted into a tidy graph object
using `tidygraph::as_tbl_graph()` to allow more sophisticated analysis and
visualisation.
```{r foodweb-tidygraph}
if (requireNamespace("tidygraph", quietly = TRUE)) {
tg <- tidygraph::as_tbl_graph(foodweb())
tg
}
```
## See also
`foodwebr` is similar to these functions/packages:
* [`mvbutils::foodweb()`](https://cran.r-project.org/package=mvbutils): The OG
of function dependency graphs in R, and the inspiration for
foodwebr. Less user-friendly output, in my opinion.
* [`DependenciesGraphs`](https://github.com/datastorm-open/DependenciesGraphs):
Provides much nicer visualisations but does not appear to be actively
maintained.