Problem: rpy2 v2 interface is arcane. Solution: Update to rpy v3!

Background

My Massive eco-evolutionary synthesis simulations python software uses a small chunk of R code internally (yes I’m ashamed of mixing programming languages, but there’s nothing I can do rn). Basically, all the ‘good’ phylogenetic tree packages are written in R and I need to simulate a big ol’ tree and evolve some traits on it. So in MESS I need to run some R code in the most compartmentalized way possible. rpy2 is a binding layer between python and R, where you can run an R instance and make calls to it and fetch data from it. Well! This is always an ugly process and we initially developed the MESS code using the rpy2 2.x branch.

The old code looked like this:

import rpy2.robjects as robjects
from rpy2.robjects import r, pandas2ri

## define the function you want to call in R (This is just a skel)
make_meta = """makeMeta <- function(a,b,c,d){}"""

# Call the function
make_meta_func = robjects.r(make_meta)
res = pandas2ri.ri2py(make_meta_func(J, S_m, speciation_rate, death_proportion, trait_rate_meta))

# Unpack the results
tree = res[0][0]
traits = pandas2ri.ri2py(res[1])
abunds = pandas2ri.ri2py(res[2])

Only god knows what’s going on will all this craziness…. I don’t know, maybe I was doing it wrong before, but it did work. Anyway, it’s one of those things where you figure it out after hours and hours and hours of work, and then you leave it alone forever and hope it never breaks. Well today I accidentally updated rpy2 to version 3.x and it broke. :(. Here’s the error message (just the relevant part):

  File "/home/isaac/Continuosity/MESS/MESS/Metacommunity.py", line 191, in _simulate_metacommunity
    res = pandas2ri.ri2py(make_meta_func(J, S_m, speciation_rate, death_proportion, trait_rate_meta))
AttributeError: module 'rpy2.robjects.pandas2ri' has no attribute 'ri2py'

Converting my code to rpy2 3.x

So I kind of squinted at this for a while, and the rolled up my sleeves. Turns out the new interface is GREAT! But the documentation is still lacking (part of why I’m adding this post). After some trial and error I figured out the new way:

from rpy2 import robjects

# Same function as before, the R code didn't change, just the python interface
make_meta = """makeMeta <- function(a,b,c,d){}"""

# Call the function
make_meta = robjects.r(make_meta)
res = make_meta(1000, 100, 2, 0.7, 1)

# Unpack the results
tree = res[0][0]
traits = np.array(res[1])
sad = np.array(res[2])

Literally a 100% improvement. The only exposure you have to the rpy2 interface is when you create the robjects.r thing (also technically having to cast the results to a numpy aray is an extra step). It is so transparent now it’s insane.

If you are reading this and you are an rpy2 developer: “You did a great job! Thank you.”

Tags:

Categories:

Updated: