Sorry, your browser cannot access this site
This page requires browser support (enable) JavaScript
Learn more >

After getting used to Python, developing scripts in R can feel quite painful. Putting aside the often-discussed issues with unclear error tracing, when scripts become slightly more complex and need to be split into multiple files, I realized R’s import mechanism is also quite frustrating… Fortunately, there’s the box package that allows module imports similar to Python’s logic.

Default Import Methods in R

R has two built-in import methods: source and library. The former essentially runs all contents of the specified R file, while the latter requires packaging the code into an R package that needs to be installed before use.

The former works well when writing relatively simple things, but problems arise when the functionality becomes more complex and needs to be split across multiple files:

  1. Namespace pollution: source() loads all objects from the script directly into the current environment, requiring additional configuration to prevent conflicts.

  2. Unclear dependencies: If there are dependencies between scripts, incorrect import order can cause errors.

  3. Difficult maintenance: From the source() part, it’s hard to see what exactly is being imported. When trying to find source code for modifications, you need to backtrack level by level, which is very troublesome.

Using library is also problematic - besides the hassle of packaging each time, namespace pollution and difficulty tracing function/object origins remain issues.

In summary, while R’s built-in methods work, they’re not very user-friendly…

Using Box

Python-style modularity: Supports box::use() syntax for module imports similar to Python’s mechanism, used as follows:

1
2
3
4
5
box::use(
plots = ./modules/plot_functions, # Import ./modules/plot_functions.R based on path
shiny_utils = shiny/utils, # Import file with object renaming
ggplot2[ggplot, aes] # Import ggplot and aes from ggplot2
)

What makes this similar to Python is that it can import specific contents from an R file without importing everything. It can also import all contents of a file into an object, then call functions within the object using mod$func(), similar to how methods are used within objects in Python.

Beyond these advantages, using box also enables relative path resolution, automatically identifying project root directories, avoiding the need to constantly switch directories with setwd(). This approach also considers cross-platform compatibility, automatically handling path format differences between Windows/Linux/macOS.

Finally, using box solves the tracing problem during imports. Whether using mod$func() or partial imports like ggplot2[ggplot, aes], you can immediately see the source of functions/objects being used, avoiding the need to search through piles of files.

Comments

Please leave your comments here