rpy-bridge is a Python-controlled R execution orchestrator (not a thin
rpy2 wrapper). It delivers deterministic, headless-safe R startup; project-root
inference; out-of-tree renv activation; isolated script namespaces; and robust
Python↔R conversions with dtype/NA normalization. Use it when you need
reproducible R execution from Python in production pipelines and CI.
Latest release: rpy-bridge on PyPI
rpy-bridge is not a thin rpy2 wrapper. Key differences:
- Infers R project roots via markers (
.git,.Rproj,renv.lock,DESCRIPTION,.here) - Activates
renveven when it lives outside the calling directory - Executes from the inferred project root so relative paths behave as R expects
- Runs headless by default (no GUI probing), isolates scripts from
globalenv() - Normalizes return values for Python (NAs, dtypes, data.frames) and offers comparison helpers
Call a package function (no scripts):
from rpy_bridge import RFunctionCaller
rfc = RFunctionCaller()
samples = rfc.call("stats::rnorm", 5, mean=0, sd=1)
median_val = rfc.call("stats::median", samples)Call a function from a local script with renv (out-of-tree allowed):
from pathlib import Path
from rpy_bridge import RFunctionCaller
project_dir = Path("/path/to/your-r-project")
script = project_dir / "scripts" / "example.R"
rfc = RFunctionCaller(path_to_renv=project_dir, scripts=script)
result = rfc.call("some_function", 42, named_arg="value")- Embeds R via
rpy2with deterministic startup behavior - Disables interactive and GUI-dependent hooks for headless execution
- Loads R scripts into isolated namespaces (not
globalenv())
- Infers R project roots using markers such as:
.git,.Rproj,renv.lock,DESCRIPTION,.here - Executes R code from the inferred project root regardless of Python CWD
- Preserves relative-path behavior expected by R scripts
- Supports R code using
here::here()or project-local data
- Activates
renvprojects located outside the calling Python directory - Sources
.Rprofileand.Renvironto reproduce R startup semantics - Does not require R scripts and
renvto live in the same directory
- Converts Python scalars, lists, dicts, and pandas objects into R equivalents
- Converts R vectors, lists, and data.frames back into Python-native types
- Handles nested structures, missing values, and mixed types robustly
- Post-processes R data.frames to fix dtype, timezone, and NA semantics
- Normalizes column types for reliable Python-side comparison
- Supports structured mismatch diagnostics between Python and R data
- Calls functions defined in sourced R scripts, base R, or installed packages
- Supports qualified function names (e.g.
stats::median) - Executes functions within the active project and library context
In addition to sourcing local R scripts, rpy-bridge supports calling functions from base R and installed packages directly from Python.
Current support includes:
- Calling base R functions without a local R script
- Executing functions from installed R packages within the active environment
Planned extensions (roadmap):
- Programmatic installation of R packages into the active
renvor system environment when explicitly enabled - Declarative package requirements at the Python call site
- Safe, opt-in package installation for CI and ephemeral environments
Package installation is intentionally not automatic by default to preserve reproducibility and avoid side effects during execution.
- System R installed and available on
PATH - Python 3.11+ (tested on 3.11–3.12)
Install rpy-bridge with rpy2 for full R support:
python3 -m pip install rpy-bridge rpy2Using uv:
uv add rpy-bridge rpy2python3 -m pip install -e .or:
uv syncrpy2pandasnumpy
See Quickstart above and examples in examples/basic_usage.py.
rpy-bridge attempts to convert Python objects to R and back. Most objects used in scientific and ML pipelines round-trip cleanly, but some heterogeneous Python structures may be wrapped or slightly altered due to differences in R’s type system.
| Python type | Round-trip fidelity | Notes |
|---|---|---|
int, float, bool, str |
High | Scalars convert directly |
Homogeneous list of numbers/strings |
High | Converted to atomic R vectors |
| Nested homogeneous lists | High | Converted to nested R lists |
pandas.DataFrame / pd.Series |
High | Converted to data.frame and normalized on return |
Mixed-type list or dict |
Partial | May be wrapped in single-element vectors |
None / pd.NA |
High | Converted to R NULL |
Helper scripts are provided in examples/r-deps/ to prepare R environments.
- Install system R dependencies (macOS / Homebrew):
bash examples/r-deps/install_r_dev_deps_homebrew.sh- Initialize an
renvproject:
source("examples/r-deps/setup_env.R")- Restore the environment on a new machine:
renv::restore()rpy-bridge is designed for:
- Python-first pipelines that rely on mature R code
- Teams where R logic must remain authoritative
- CI or production systems that cannot rely on interactive R sessions
- Multi-repo or multi-directory projects with non-trivial filesystem layouts
It is not intended as a convenience wrapper for exploratory R usage.
- rpy-bridge is released under the MIT License © 2025 Victoria Cheung
- Depends on
rpy2, licensed under the GNU GPL (v2 or later)
This package was spun out of internal tooling I wrote at Revolution Medicines. Thanks to the team there for supporting its open-source release.