Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Sympify() and Eval() Equations Not Executing Within a Function

I am writing a script which reads values from a CSV through pandas into a DataFrame. The values, 'A' and 'B', are inputs into an equation. This equation is obtained from an XML output file from an external program. The equation provides a result for 'A' and 'B' row-by-row of the DataFrame and places those results back into the original DataFrame.

If I make a function definition, explicitly write the equation in the definition, and return that that equation, things work fine. e.g.,

import pandas as pd

dataFrame = pd.read_csv() # Reads CSV to "dataFrame"
A = dataFrame['A'] # Defines A as row A in "dataFrame"
B = dataFrame['B'] # Defines B as row B in "dataFrame"

def Func(a,b):
    P = 2*a+3*b
    return P

outPut['P'] = Func(A, B) # Assigns a value to each row in "outPut" for each 'A' and 'B' per row of "dataFrame"

However, what I really want to do is "build" that same equation from an XML file rather than entering it in explicitly. So, I basically pull 'terms' and 'coefficients' from the xml file and result in a string form of the equation. I then convert the string to an executable function using sympy.sympify(). e.g.,

import pandas as pd
import sympy as sy
import xml.etree.ElementTree as etree

dataFrame = pd.read_csv() # Reads CSV to "dataFrame"
A = dataFrame['A']  # Defines A as row A in "dataFrame"
B = dataFrame['B']  # Defines B as row B in "dataFrame"

tree = etree.parse('C:\...')
.
..(some XML stuff with etree)
.
equationString = "some code that grabs terms and coefficients from XML file" # Builds equation from XML  'terms' and 'coefficients'

P = sy.sympify(equationString)

def Func(A, B):
    global P    
    return P

outPut['P'] = Func(A, B) # Assigns a value to each row in "outPut" for each 'A' and 'B' per row of "dataFrame"

The result is that when I call to execute this equation over the dataFrame the literal equation is copied into the "outPut" DF rather than the row by row result for each 'A' and 'B'. I don't understand why Python sees these code examples differently, nor how to achieve the result I want from the first example. For some reason the sympify() result is not executable. The same seems to occur when I use eval().

like image 285
zachn Avatar asked Aug 12 '26 11:08

zachn


1 Answers

Elaborating on my comment, here's how to solve the problem with lambdify

In [1]: import sympy as sp

In [2]: import pandas as pd

In [3]: import numpy as np

In [4]: df = pd.DataFrame(np.random.randn(5,2), columns=['A', 'B'])

In [5]: equationString = "2*A+3*B"

In [7]: expr = sp.S(equationString)

In [8]: expr
Out[8]: 2*A + 3*B

In [10]: f = sp.lambdify(sp.symbols("A B"), expr, modules="numpy")

In [11]: f(df['A'],df['B'])
Out[11]: 
0   -2.779739
1   -1.176580
2    3.911066
3    1.888639
4    0.745293
dtype: float64

In [12]: 2*df["A"]+3*df["B"] - f(df["A"],df["B"])
Out[12]: 
0    0
1    0
2    0
3    0
4    0
dtype: float64

Depending on the expressions encountered in your xml file, sympy may be overkill. Here's how to use eval

In [1]: import pandas as pd

In [2]: import numpy as np

In [3]: df = pd.DataFrame(np.ran
np.random  np.rank    

In [3]: df = pd.DataFrame(np.random.randn(5, 2), columns=['A', 'B'])

In [4]: equationString = "2*A+3*B"

In [5]: f = eval("lambda A, B: "+equationString)

In [6]: f(df['A'],df['B'])
Out[6]: 
0    1.094797
1   -1.942295
2   -5.181502
3    1.888990
4    3.069017
dtype: float64

In [7]: 2*df["A"]+3*df["B"] - f(df["A"],df["B"])
Out[7]: 
0    0
1    0
2    0
3    0
4    0
dtype: float64
like image 94
ptb Avatar answered Aug 15 '26 07:08

ptb



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!