A couple of python utilities that make R.NET easier to use

Jul 15, 2011 at 10:31 PM
Edited Jul 15, 2011 at 10:33 PM

First: a method to turn a python dictionary into an R data frame. The dictionary keys should be the column names. Under each key should be a numpy array with the values for that column. The columns should be all of the same length:

 

#Move a dictionary into an R data frame
def Dictionary_to_RDotNet(data_dictionary):
        
    #set up variables we'll need later
    df = dict()
    cols = dict()
    command = "data.frame("
    
    #each column of the dictionary should be a numpy array
    for col in data_dictionary:
        if data_dictionary[col].dtype in [int, float]:
            df[col] = r.CreateNumericVector( Array[float](data_dictionary[col]) ).AsVector()
        else:
            df[col] = r.CreateCharacterVector( Array[str](data_dictionary[col]) ).AsVector()
        
        #Update the command and give the column a random name in R
        col_name = "col_" + str(random.random())[2:]
        command = command + col + "=" + col_name + ","
        r.SetSymbol(col_name, df[col])
        
    #create the data frame in R
    command = command[:-1] + ")"
    data_frame = r.EagerEvaluate(command).AsDataFrame()

	#if a name was supplied, then assign it to the R data.frame object:
	if name: r.SetSymbol(name, data_frame)

    return data_frame

 

 

Second: a wrapper class that makes it easier  to call functions in R. If you have, e.g., a data frame called df (as returned by Dictionary_to_RDotNet), and an R_Wrap object rw, then you can call the lm function this way: rw.Call(function='lm', data=df)

#This class wraps the R.NET functionality and makes calling r functions simpler.
class R_Wrap():
    def __init__(self):
        self.r = r
        random.seed( datetime.now().microsecond ) #we'll use random numbers to name objects in r
        
    def Call(self, function, **params):
        #This function translates function calls into a form that R.NET can understand
        
        #start the command string with the function name:
        command = str(function) + "("
        
        for item in params:
            if isinstance(params[item], str): pass #strings are ok
            
            elif isinstance(params[item], bool): #convert boolean types to T or F
                if params[item] is True: params[item] = "TRUE"
                else: params[item] = "FALSE"    
            
            elif isinstance(params[item], (float, int)): #convert numeric types to strings
                params[item] = str(params[item])

            elif isinstance(params[item], RDotNet.SymbolicExpression):
                #make sure we have a name by which we can refer to R objects
                robj_name = "r_" + str(random.random())[2:]
                r.SetSymbol(robj_name, params[item])
                params[item] = robj_name
                
            elif isinstance(params[item], (np.ndarray, list)):
                temp = np.array( params[item] )
                
                #move the array into R
                if temp.dtype in [int, float]:
                    temp = r.CreateNumericVector( Array[float](temp) ).AsVector()
                else:
                    temp = r.CreateCharacterVector( Array[str](temp) ).AsVector()
                    
                #make sure we have a name by which we can refer to R objects
                robj_name = "r_" + str(random.random())[2:]
                r.SetSymbol(robj_name, temp)
                params[item] = robj_name
                
            #Now piece together the R function call:
            command = command + item + "=" + params[item] + ","
            
        command = command[:-1] + ")"
        
        result = self.r.EagerEvaluate(command)
        return result