Closed rluce closed 2 years ago
This may be simpler than I thought: just split the string on the comparator and use pd.eval() for left and right substrings.
Unfortunately this cannot work, Dataframe.eval
seems entirely incompatible with arithmetic on object dtypes. We have to roll our own eval logic:
>>> import gurobipy as gp
>>> import pandas as pd
>>> import gurobipy_pandas
>>> df = pd.RangeIndex(3).grb.pd_add_vars(m, name='x').to_frame()
>>> df
x
0 <gurobi.Var x[0]>
1 <gurobi.Var x[1]>
2 <gurobi.Var x[2]>
>>> df.eval("x + 1")
...
TypeError: unsupported operand type(s) for +: 'object' and '<class 'int'>'
>>> df.eval("x + 1", parser='python')
...
TypeError: unsupported operand type(s) for +: 'object' and '<class 'int'>'
>>> df.eval("x + 1", engine='python')
...
TypeError: unsupported operand type(s) for +: 'object' and '<class 'int'>'
IMO it would be very good to have this string expression based API for adding constraints using a column relation (see regression.py for context).
This currently works but with a really basic implementation and I can see it having a lot of dodgy edge-cases.
pandas.DataFrame.eval
has some well-defined behaviour (e.g. clear split between column names and local variables) but doesn't work out of the box for this use case as it is targeted at numeric types. We should try to leverage at least some of pandas' in-built functions here to avoid surprises.