Mapping python tuple and R list with rpy2? - python

I'm having some trouble to understand the mapping with rpy2 object and python object.
I have a function(x) which return a tuple object in python, and i want to map this tuple object with R object list or vector.
First, i'm trying to do this :
# return a python tuple into this r object tlist
robjects.r.tlist = get_max_ticks(x)
#Convert list into dataframe
r('x <- as.data.frame(tlist,row.names=c("seed","ticks"))')
FAIL with error :
rinterface.RRuntimeError: Error in eval(expr, envir, enclos) : object 'tlist' not found
So i'm trying an other strategy :
robjects.r["tlist"] = get_max_ticks(x)
r('x <- as.data.frame(tlist,row.names=c("seed","ticks"))')
FAIL with this error :
TypeError: 'R' object does not support item assignment
Could you help me to understand ?
Thanks a lot !!

Use globalEnv:
import rpy2.robjects as ro
r=ro.r
def get_max_ticks():
return (1,2)
ro.globalEnv['tlist'] = ro.FloatVector(get_max_ticks())
r('x <- as.data.frame(tlist,row.names=c("seed","ticks"))')
print(r['x'])
# tlist
# seed 1
# ticks 2
It may be possible to access symbols in the R namespace with this type of notation: robjects.r.tlist, but you can not assign values this way. The way to assign symbol is to use robject.globalEnv.
Moreover, some symbols in R may contain a period, such as data.frame. You can not access such symbols in Python using notation similar to robjects.r.data.frame, since Python interprets the period differently than R. So I'd suggest avoiding this notation entirely, and instead use
robjects.r['data.frame'], since this notation works no matter what the symbol name is.

You could also avoid the assignment in R all together:
import rpy2.robjects as ro
tlist = ro.FloatVector((1,2))
keyWordArgs = {'row.names':ro.StrVector(("seed","ticks"))}
x = ro.r['as.data.frame'](tlist,**keyWordArgs)
ro.r['print'](x)

Related

How Can I Convert a String to a Ufunc?

I am trying to write a simple function that converts an input written in LaTeX to a ufunc that can be read by numpy. So far, I'm testing the function by converting \sin(x) to np.sin(x) (ignoring the conversion from {} to (). I'm not that familiar with ufuncs so I keep running into an error when trying to convert the \sin(x) string to the np.sin(x) ufunc for any given x.
import numpy as np
latexEq = input()
def latexMap(latexEq):
if "\sin" in latexEq:
sinLatex = latexEq.replace("\sin", "np.sin")
else:
pass
return sinLatex
npOutput = np.ufunc(latexMap(latexEq))
print(f"f(x)={numpyOutput}")
Similar to how an integer may be converted into a string str(2), I tried enclosed both sinLatex, latexEq, "np.sin", and npOutput but the error I always receive is
TypeError: cannot create 'numpy.ufunc' instances
Any explanation would be appreciated.
So if you just have npOutput = "np.sin" (without the (x)) you can do
# function_name = getattr(module, function_name_string)
npOutput = getattr(np, npOutput.lstrip("np."))
which gives you the function np.sin. The parentheses have to be gone because otherwise it would be a function call, not a function.

Call many python functions from a module by looping through a list of function names and making them variables

I have three similar functions in tld_list.py. I am working out of mainBase.py file.
I am trying to create a variable string which will call the appropriate function by looping through the list of all functions. My code reads from a list of function names, iterates through the list and running the function on each iteration. Each function returns 10 pieces of information from separate websites
I have tried 2 variations annotated as Option A and Option B below
# This is mainBase.py
import tld_list # I use this in conjunction with Option A
from tld_list import * # I use this with Option B
functionList = ["functionA", "functionB", "functionC"]
tldIterator = 0
while tldIterator < len(functionList):
# This will determine which function is called first
# In the first case, the function is functionA
currentFunction = str(functionList[tldIterator])
Option A
currentFunction = "tld_list." + currentFunction
websiteName = currentFunction(x, y)
print(websiteName[1]
print(websiteName[2]
...
print(websiteName[10]
Option B
websiteName = currentFunction(x, y)
print(websiteName[1]
print(websiteName[2]
...
print(websiteName[10]
Even though it is not seen, I continue to loop through the iteration by ending each loop with tldIterator += 1
Both options fail for the same reason stating TypeError: 'str' object is not callable
I am wondering what I am doing wrong, or if it is even possible to call a function in a loop with a variable
You have the function names but what you really want are the function objects bound to those names in tld_list. Since function names are attributes of the module, getattr does the job. Also, it seems like list iteration rather than keeping track of your own tldIterator index would suffice.
import tld_list
function_names = ["functionA", "functionB", "functionC"]
functions = [getattr(tld_list, name) for name in function_names]
for fctn in functions:
website_name = fctn(x,y)
You can create a dictionary to provide a name to function conversion:
def funcA(...): pass
def funcB(...): pass
def funcC(...): pass
func_find = {"Huey": funcA, "Dewey": funcB, "Louie": FuncC}
Then you can call them, e.g.
result = func_find["Huey"](...)
You should avoid this type of code. Try using if's, or references instead. But you can try:
websiteName = exec('{}(x, y)'.format(currentFunction))

Change the index symbol of a FormalPowerSeries in Sympy

If I construct a FormalPowerSeries of an expression, the default symbol used as an indexing variable is k. This is not an inherent problem, but I'd like to adhere to the conventions of other formal texts where n is used.
from sympy.series.formal import FormalPowerSeries, fps
gfps: FormalPowerSeries = fps(1/(1-z))
display(gfps)
# Workaround utility to find the first dummy with a given name
def findDummy(expr: Expr, name: str) -> Dummy:
from sympy.utilities.iterables import default_sort_key
return next(filter(
lambda s: isinstance(s, Dummy) and s.name == name,
sorted(expr.free_symbols, key=default_sort_key)))
# Workaround, replace the dummy `k` with another dummy, `n`
form = (gfps.ak.formula * gfps.xk.formula)
k: Dummy = findDummy(gfps, 'k')
gfps = gfps.xreplace({k: Dummy('n', integer=True)})
display(gfps)
The first call to display yields the following
when i would prefer to have
.
While I could construct an instance of Sum from the form variable, I'd prefer to keep the semantics of a FormalPowerSeries datatype. My current workaround works for toy problems, but I am uncertain yet if it breaks any of the underlying machinery or if there is a canonical way to perform this re-indexing.
Using xreplace is a valid way to change a symbol in an expression.

Updating the values of variables inside a namedtuple() structure

I want to create a structure, as we do in C, in python. I have tried to use namedtuple() for this. However, I can not update the values of variables I have described inside the custom structure.
Here is how i declared it:
from collections import namedtuple as nt
Struct = nt('Struct','all left right bottom top near far')
And this is what i am trying to do in a method :
class codeClip:
def compOutCode(x,y,z,xmin,xmax,ymin,ymax,zmin,zmax):
code = Struct(0,0,0,0,0,0,0)
if(y > ymax):
code.top = 1
code.all += code.top
elif(y < ymin):
code.bottom = 1
return code
However it is giving this error:
code.top = 1
AttributeError: can't set attribute
What should I do? Pardon me, I am fairly new in python, so still getting used to all of these.
You may use the _replace() method.
Instead of code.top = 1, you can update values as follows.
code = code._replace(top = 1)
Please note, named tuples are immutable, so you cannot manipulate them. If you want something mutable, you can use recordtype.
Reference: https://stackoverflow.com/a/31253184/5352399

Python 3.0 - Dynamic Class Instance Naming

I want to use a while loop to initialize class objects with a simple incremented naming convention. The goal is to be able to scale the number of class objects at will and have the program generate the names automatically. (ex. h1...h100...h1000...) Each h1,h2,h3... being its own instance.
Here is my first attempt... have been unable to find a good example.
class Korker(object):
def __init__(self,ident,roo):
self.ident = ident
self.roo = roo
b = 1
hwinit = 'h'
hwstart = 0
while b <= 10:
showit = 'h' + str(b)
print(showit) #showit seems to generate just fine as demonstrated by print
str(showit) == Korker("test",2) #this is the line that fails
b += 1
The errors I get range from a string error to a cannot use function type error.... Any help would be greatly appreciated.
If you want to generate a number of objects, why not simply put them in an array / hash where they can be looked up later on:
objects = {}
for b in range(1,11):
objects['h'+str(b)] = Korker("test", 2)
# then access like this:
objects['h3']
Of course there are ways to make the names available locally, but that's not a very good idea unless you know why you need it (via globals() and locals()).
Variables are names that point to objects that hold data. You are attempting to stick data into the variable names. That's the wrong way around.
instead of h1 to h1000, just call the variable h, and make it a list. Then you get h[0] to h[999].
Slightly different solution to viraptor's: use a list.
h = []
for i in range(10):
h.append(Korker("test",2))
In fact, you can even do it on one line with a list comprehension:
h = [Korker("test", 2) for i in range(10)]
Then you can get at them with h[0], h[1] etc.

Categories

Resources