Python interface to the R language (embedded R)
—
Work with R environments, scoping, and evaluation contexts for advanced R programming patterns from Python, including variable management, namespace isolation, and function scoping.
R environments provide variable scoping and namespace management with dict-like Python interface.
class Environment(RObject):
"""
R environment wrapper with dict-like interface.
Provides Python-style access to R environments for
variable storage, scoping, and namespace management.
"""
def __getitem__(self, key: str):
"""
Get variable from environment.
Parameters:
- key: Variable name
Returns:
R object value
Raises:
KeyError: If variable not found
"""
def __setitem__(self, key: str, value):
"""
Set variable in environment.
Parameters:
- key: Variable name
- value: Value to assign (converted to R object)
"""
def __delitem__(self, key: str):
"""
Remove variable from environment.
Parameters:
- key: Variable name to remove
Raises:
KeyError: If variable not found
"""
def __contains__(self, key: str) -> bool:
"""
Check if variable exists in environment.
Parameters:
- key: Variable name
Returns:
True if variable exists
"""
def keys(self):
"""
Get all variable names in environment.
Returns:
Iterator over variable names
"""
def values(self):
"""
Get all values in environment.
Returns:
Iterator over variable values
"""
def items(self):
"""
Get all name-value pairs in environment.
Returns:
Iterator over (name, value) tuples
"""
def get(self, key: str, default=None):
"""
Get variable with default value.
Parameters:
- key: Variable name
- default: Default value if not found
Returns:
Variable value or default
"""Predefined R environments for different scoping contexts.
# Global environments
globalenv: Environment # R global environment (.GlobalEnv)
baseenv: Environment # R base environment
emptyenv: Environment # R empty environment
# Access to current environments
def get_globalenv() -> Environment:
"""Get R global environment."""
def get_baseenv() -> Environment:
"""Get R base environment."""
def get_emptyenv() -> Environment:
"""Get R empty environment."""Create new R environments with specified parent environments.
def new_env(parent=None, hash: bool = True, size: int = 29) -> Environment:
"""
Create new R environment.
Parameters:
- parent: Parent environment (default: global environment)
- hash: Use hash table for variable lookup (default: True)
- size: Initial hash table size (default: 29)
Returns:
New environment instance
"""Manage evaluation contexts and temporary environments.
def local_context(env: Environment = None, use_rlock: bool = True):
"""
Context manager for local R evaluation environment.
Parameters:
- env: Environment to use (default: new environment)
- use_rlock: Use R's thread lock for safety (default: True)
Returns:
Context manager that sets evaluation environment
Usage:
with local_context() as env:
# Code here evaluates in local environment
env['x'] = 42
result = r('x + 10') # Uses local x
# x no longer accessible outside context
"""
class evaluation_context:
"""
Context variable managing current R evaluation environment.
Used internally by rpy2 to track the active environment
for R code evaluation and variable resolution.
"""
def get(self) -> Environment: ...
def set(self, env: Environment): ...Navigate and manipulate R environment inheritance chains.
class Environment:
@property
def parent(self) -> Environment:
"""Get parent environment in inheritance chain."""
@parent.setter
def parent(self, env: Environment):
"""Set parent environment."""
def parents(self):
"""
Iterate through parent environments.
Yields:
Environment objects from current to base environment
"""
def find(self, name: str) -> Environment:
"""
Find environment containing variable.
Parameters:
- name: Variable name to search for
Returns:
Environment containing the variable
Raises:
KeyError: If variable not found in hierarchy
"""Helper functions for environment inspection and manipulation.
def env_to_list(env: Environment) -> dict:
"""
Convert environment to Python dictionary.
Parameters:
- env: Environment to convert
Returns:
Dictionary with environment contents
"""
def list_to_env(data: dict, parent: Environment = None) -> Environment:
"""
Create environment from Python dictionary.
Parameters:
- data: Dictionary with variable names and values
- parent: Parent environment (default: global environment)
Returns:
New environment with dictionary contents
"""
def env_size(env: Environment) -> int:
"""
Get number of variables in environment.
Parameters:
- env: Environment to measure
Returns:
Number of variables
"""
def env_ls(env: Environment, all_names: bool = False) -> list:
"""
List variable names in environment.
Parameters:
- env: Environment to list
- all_names: Include hidden variables (starting with .)
Returns:
List of variable names
"""import rpy2.robjects as ro
from rpy2.robjects import r, globalenv
from rpy2.robjects.environments import Environment
# Access global environment
print(f"Variables in global env: {list(globalenv.keys())}")
# Set variables in global environment
globalenv['my_var'] = ro.IntVector([1, 2, 3, 4, 5])
globalenv['my_string'] = 'Hello from Python'
# Access variables from R
result = r('mean(my_var)')
print(f"Mean: {result[0]}")
# Check if variables exist
if 'my_var' in globalenv:
print("my_var exists in global environment")
# Get variable with default
value = globalenv.get('nonexistent_var', 'default_value')
print(f"Value: {value}")
# Create new environment
my_env = ro.robjects.environments.new_env()
my_env['local_var'] = ro.FloatVector([1.1, 2.2, 3.3])
# Environment hierarchy
print(f"Parent of my_env: {my_env.parent}")
# Find environment containing variable
env_with_var = globalenv.find('my_var')
print(f"Found my_var in: {env_with_var}")
# Use local context for temporary variables
with ro.robjects.environments.local_context() as local_env:
local_env['temp_var'] = 42
local_env['temp_list'] = ro.IntVector([10, 20, 30])
# These variables are only available in this context
result = r('temp_var + sum(temp_list)')
print(f"Local result: {result[0]}")
# temp_var and temp_list are no longer accessible
try:
print(globalenv['temp_var'])
except KeyError:
print("temp_var not found in global environment (as expected)")
# Environment as dictionary
env_dict = {
'x': ro.IntVector([1, 2, 3]),
'y': ro.FloatVector([1.1, 2.2, 3.3]),
'name': 'test_environment'
}
dict_env = ro.robjects.environments.list_to_env(env_dict)
print(f"Variables in dict_env: {list(dict_env.keys())}")
# Convert environment back to dictionary
back_to_dict = ro.robjects.environments.env_to_list(dict_env)
print(f"Back to dict: {back_to_dict.keys()}")
# Environment iteration
print("All variables and values in global environment:")
for name, value in globalenv.items():
print(f" {name}: {type(value)}")
# Environment cleanup
del globalenv['my_var']
del globalenv['my_string']
# Working with package environments
stats_env = ro.packages.importr('stats').__renv__
print(f"Functions in stats package: {len(list(stats_env.keys()))}")
# Search path environments (R search() equivalent)
search_envs = []
current = globalenv
while current is not None:
search_envs.append(current)
try:
current = current.parent
except:
break
print(f"Number of environments in search path: {len(search_envs)}")# Environment-based namespacing
class RNamespace:
"""Python class wrapping R environment for namespace management."""
def __init__(self, name):
self.name = name
self.env = ro.robjects.environments.new_env()
globalenv[name] = self.env
def __setattr__(self, name, value):
if name in ['name', 'env']:
super().__setattr__(name, value)
else:
self.env[name] = value
def __getattr__(self, name):
return self.env[name]
# Create namespace
my_namespace = RNamespace('my_package')
my_namespace.utility_function = r('function(x) x^2')
my_namespace.constant = 3.14159
# Use from R
result = r('my_package$utility_function(5)')
print(f"Result: {result[0]}") # 25.0
# Function factories with closures
def create_r_function_factory(base_env):
"""Create R functions with specific environment closures."""
factory_env = ro.robjects.environments.new_env(parent=base_env)
factory_env['multiplier'] = 10
with ro.robjects.environments.local_context(factory_env):
r_function = r('''
function(x) {
x * multiplier
}
''')
return r_function
# Create function with closure
multiplier_func = create_r_function_factory(globalenv)
result = multiplier_func(ro.IntVector([1, 2, 3, 4, 5]))
print(f"Multiplied: {list(result)}") # [10, 20, 30, 40, 50]Install with Tessl CLI
npx tessl i tessl/pypi-rpy2