Unable to move R analyses output back to Python (rpy2)

Viewed 203

I am attempting to pass some data from python to R and then retun the results to a python but can't seem to get it to work.

I am successful in passing my data to R and running my custom function on the data and even get the output. Where I am stuck is getting the statistical output back into python as a dataframe. I have tried using rpy2 and even exporting it to a .csv file to re-import but can't get either method to work. When I try and push it back to pandas I get an error that is cant be coerced. When it comes to saving to a .csv I can't seem to get it to work using my "results" object. In reading it seems that checking what is in the R global environment may help me figure it out but I haven't been able to figure out how to do that either.

Any helpful comments are appreciated.


#import statements
import rpy2
print(rpy2.__version__)
import rpy2.robjects as robjects
from rpy2.robjects.packages import importr
import rpy2.robjects.numpy2ri
rpy2.robjects.numpy2ri.activate()
base = importr('base')
utils = importr('utils')
name = 'test_subject'

#Sample data to analyze
list1 = [0,1,2,3,4,5,6,7,8,9,10] # analysis window
list2 = [1,5,6,8,7,9,10,8,7,6,3] # nnumber of responses per bin

#Convert data to R objects
set1 = robjects.IntVector(list1)
set2 = robjects.IntVector(list2)

makeDataFrame = robjects.r('''data.frame ''')
df = makeDataFrame(x = set1, y = set2)


# Create curve fitting function
curve_fit = robjects.r('''
curve_fit <- function(df, plot = FALSE){ control <- nls.control(maxiter = 1000, tol = 0.000100, minFactor = 1/2064,
                         printEval = FALSE, warnOnly = TRUE)
  
  fit <- nls(y ~ d+a*exp(-.5*((x-t0)/b)^2)+c*(x-t0), 
             data = df,
             start = list(a = 1, b = 10, t0 = 10, c = 1, d = 1),
             algorithm = "port",
             control = control)
  
  if (plot){
    fitFnc <- function(x) predict(fit, list(x=x))
    par(mfrow = c(1, 1))
    plot(df$x, df$y, xlim = c(0,45))
    curve(fitFnc, from=.5, to=45, add = TRUE)
  }

  return(list("params" = summary(fit), 
              "r2" = cor(predict(fit), df$y)^2))
              }''')

#run function on data
results = curve_fit(df, plot = True)

#Show Results
print('results', results)
print(type(results))
1 Answers

The problem was in

return(list("params" = summary(fit), "r2" = cor(predict(fit), df$y)^2))

The first item in the list "params" was a summary table from R. While this printed in python as the data I wanted it was a single object that could not be subdivided as it was essentially and image of an R output table. What I needed to return was a dataframe as shown in the code below.

return(data.frame(coef(summary(fit)), r2 = cor(predict(fit), df$y)^2))

This returned a list of objects that I could then convert to a numpy array and manipulate in python.

Here is the full code.

#import statements
import rpy2
print(rpy2.__version__)
import rpy2.robjects as robjects
from rpy2.robjects.packages import importr
import rpy2.robjects.numpy2ri
import numpy as np
rpy2.robjects.numpy2ri.activate()
base = importr('base')
utils = importr('utils')




#Sample data to analyze
list1 = [0,1,2,3,4,5,6,7,8,9,10] # analysis window
list2 = [1,5,6,8,7,9,10,8,7,6,3] # nnumber of responses per bin

#Convert data to R objects and place in data frame
set1 = robjects.IntVector(list1)
set2 = robjects.IntVector(list2)

makeDataFrame = robjects.r('''data.frame ''')
df = makeDataFrame(x = set1, y = set2)


# Create curve fitting function in r
curve_fit = robjects.r('''

#Fit function
curve_fit <- function(df, plot = FALSE){ control <- nls.control(maxiter = 1000, tol = 0.000100, minFactor = 1/2064,
                         printEval = FALSE, warnOnly = TRUE)
#Specify formula to fit  
  fit <- nls(y ~ d+a*exp(-.5*((x-t0)/b)^2)+c*(x-t0), 
             data = df,
             start = list(a = 1, b = 10, t0 = 10, c = 1, d = 1),
             algorithm = "port",
             control = control)
             
# Create plot of curve 
  if (plot){
    fitFnc <- function(x) predict(fit, list(x=x))
    par(mfrow = c(1, 1))
    plot(df$x, df$y, xlim = c(0,45))
    curve(fitFnc, from=.5, to=45, add = TRUE)}

    #returns data in R dataframe
  return(data.frame(coef(summary(fit)), r2 = cor(predict(fit), df$y)^2))

               }''')


#run function on data
results = curve_fit(df, plot = True)

results = np.array(results) #convert to numpy array

#Show Results
print('results', results)
print(type(results))
Related