Closed Dr-Irv closed 1 year ago
The index accessor should already work for this. Note that as with gurobipy, the name is not the first (or in this case, second, after model) positional argument, so to use it this way name
must be a kwarg:
>>> s = pd.Series(range(5), index=range(5))
>>> myvars = s.index.grb.pd_add_vars(m, name="x")
>>> m.update()
>>> myvars
0 <gurobi.Var x[0]>
1 <gurobi.Var x[1]>
2 <gurobi.Var x[2]>
3 <gurobi.Var x[3]>
4 <gurobi.Var x[4]>
Name: x, dtype: object
For the series accessor, would you expect s.grb.pd_add_vars(m, name="x")
to return the same series as s.index.grb.pd_add_vars(m, name="x")
? Should it return a dataframe which joins the variables to the original series data? Would the series data be used in any way?
I have not implemented this in the series accessor yet since there I could not see any consistent way to use the series data (unlike the dataframe accessor, where you may have multiple named columns which specify objective, bounds, etc), so it seemed to make more sense for the user to explicitly point to the index and build a new series from that.
For the series accessor, would you expect
s.grb.pd_add_vars(m, name="x")
to return the same series ass.index.grb.pd_add_vars(m, name="x")
?
Yes.
Should it return a dataframe which joins the variables to the original series data?
I'd vote just a Series
. You could make this an additional keyword argument.
Would the series data be used in any way?
I don't think so, although maybe you'd like to say "use the series for LB" or "use the series for UB" or "use the series for the objective" via some keyword argument.
I did my first model, and there are inconsistencies in the API that are a bit annoying.
DataFrame
and create variables, it returns a DataFrame
with the appended column of the variables. I think it should return the Series
, and then it is my choice as to whether to append the variables to the DataFrame that was passed in, or keep it in a separate Series. Here's an example:
Make = rmDF.grb.pd_add_vars(model, "Make")["Make"]
In the above, I had to extract the series. I think it is more natural to have pd_add_vars
just return a Series
. If I want to append it (assuming a return result of a Series), I could probably do
rmDF = pd.concat([rmDF, rmDF.grb.pd_add_vars(model, "Make")], axis=1)
When I made variables from an Index
, I wrote this and it worked:
Inv = invindex.grb.pd_add_vars(model, name="Inv")
I'm going to slightly agree with @Dr-Irv on this one. In some ways I like that it returns the full pd.DataFrame
, but it was definitely not what I expected, as I expected the exact same behavior as Irv. However, it allows me to chain variable creation if they are all built using the same index, which often happens when building models:
df = df.grb.pd_add_vars(m, "x").grb.pd.add_vars(m, "y")
and you get a pd.DataFrame
back with both variables added to it. I do think Irv's thought of returning a pd.Series
is probably more pandonic and would allow you to do this instead of what I said above:
df = df.assign(x=lambda df: df.grb.pd_add_vars(m, "x"),
y=lambda df: df.grb.pd_add_vars(m, "y"))
You may want to consider making pd_add_vars()
and pd_add_constrs()
top level functions, as opposed to hanging off the accessors. So instead of:
Make = rmDF.grb.pd_add_vars(model, "Make")["Make"]
you could have:
import gurobipy_pandas as grbp
Make = grbp.add_vars(model, rmDF, "Make")
That would allow you to easily add type hints for pd_add_vars()
and pd_add_constrs()
You could even consider extending the gurobipy
API (although that might not be possible as open source):
Make = model.pd_add_vars(rmDF, "Make")
One advantage of this is that the pd_add_vars()
and pd_add_constrs()
could take a DataFrame, Series, or Index as an argument, and always return a Series
.
You could then just use the .grb
accessor to access attributes, and the accessor would only apply to Series
. You wouldn't be able to type-hint those (unless you only provide them on Series
of gurobi objects with a subclass of Series
).
Thanks both!
I'd want to be able to do
Series.grb
andIndex.grb
, as in the following: