Gurobi / gurobipy-pandas

Convenience wrapper for building optimization models from pandas data
https://gurobipy-pandas.readthedocs.io/en/stable/
Apache License 2.0
83 stars 15 forks source link

Accept index mappers in pd_add_vars to transform an index entry to a string used in var name #34

Closed rluce closed 1 year ago

simonbowly commented 1 year ago

Added an index_formatter argument to all variants of add_vars and add_constrs (both accessors and global functions). Details are documented in docs/source/naming.rst, here are the key bits:

If no argument is provided, default replacement of illegal characters and whitespace with underscores:

>>> location_index = pd.Index(["Mount Everest", "Mariana Trench"], name='location')
>>> datetime_index = pd.date_range(start=pd.Timestamp(2022, 11, 9), freq='D', periods=2, name='date')
>>> index = pd.MultiIndex.from_product([location_index, datetime_index])
>>> index
MultiIndex([( 'Mount Everest', '2022-11-09'),
            ( 'Mount Everest', '2022-11-10'),
            ('Mariana Trench', '2022-11-09'),
            ('Mariana Trench', '2022-11-10')],
            names=['location', 'date'])
>>> height = gppd.add_vars(model, index, name="height")
>>> model.update()
>>> height.gppd.VarName    # doctest: +NORMALIZE_WHITESPACE
location        date
Mount Everest   2022-11-09     height[Mount_Everest,2022_11_09T00_00_00]
                2022-11-10     height[Mount_Everest,2022_11_10T00_00_00]
Mariana Trench  2022-11-09    height[Mariana_Trench,2022_11_09T00_00_00]
                2022-11-10    height[Mariana_Trench,2022_11_10T00_00_00]
Name: height, dtype: object

index_formatter='disable' switches off the behaviour:

>>> height = gppd.add_vars(model, index, name="height", index_formatter='disable')
>>> model.update()
>>> height.gppd.VarName
location        date
Mount Everest   2022-11-09     height[Mount Everest,2022-11-09 00:00:00]
                2022-11-10     height[Mount Everest,2022-11-10 00:00:00]
Mariana Trench  2022-11-09    height[Mariana Trench,2022-11-09 00:00:00]
                2022-11-10    height[Mariana Trench,2022-11-10 00:00:00]
Name: height, dtype: object

Apply a function to each level in the index. If the user passes a mapping, this specifies functions to be applied to named index levels. If the user passes a callable, the callable is applied to every index level.

>>> index_formatter = {"date": lambda index: index.strftime("%y%m%d")}
>>> height = gppd.add_vars(model, index, name="height", index_formatter=index_formatter)
>>> model.update()
>>> height.gppd.VarName    # doctest: +NORMALIZE_WHITESPACE
location        date
Mount Everest   2022-11-09     height[Mount_Everest,221109]
                2022-11-10     height[Mount_Everest,221110]
Mariana Trench  2022-11-09    height[Mariana_Trench,221109]
                2022-11-10    height[Mariana_Trench,221110]
Name: height, dtype: object