Skip to content

model_element

Classes:

Name Description
ModelElement
ModelElementWithId

Provides a method that assigns a unique ID to each row in a DataFrame.

SupportPolarsMethodMixin

ModelElement(data, **kwargs)

Bases: ABC

Methods:

Name Description
__len__
on_add_to_model

Attributes:

Name Type Description
data DataFrame
dimensions Optional[List[str]]

The names of the data's dimensions.

dimensions_unsafe List[str]

Same as dimensions but returns an empty list if there are no dimensions instead of None.

friendly_name str
name
shape Dict[str, int]

The number of indices in each dimension.

Source code in pyoframe/model_element.py
def __init__(self, data: pl.DataFrame, **kwargs) -> None:
    # Sanity checks, no duplicate column names
    assert len(data.columns) == len(set(data.columns)), (
        "Duplicate column names found."
    )

    cols = _get_dimensions(data)
    if cols is None:
        cols = []
    cols += [col for col in RESERVED_COL_KEYS if col in data.columns]

    # Reorder columns to keep things consistent
    data = data.select(cols)

    # Cast to proper dtype
    if COEF_KEY in data.columns:
        data = data.cast({COEF_KEY: pl.Float64})
    if VAR_KEY in data.columns:
        data = data.cast({VAR_KEY: KEY_TYPE})
    if QUAD_VAR_KEY in data.columns:
        data = data.cast({QUAD_VAR_KEY: KEY_TYPE})

    self._data = data
    self._model: Optional[Model] = None
    self.name = None
    super().__init__(**kwargs)

data property

dimensions property

The names of the data's dimensions.

Examples:

>>> # A variable with no dimensions
>>> pf.Variable().dimensions
>>> # A variable with dimensions of "hour" and "city"
>>> pf.Variable(
...     [
...         {"hour": ["00:00", "06:00", "12:00", "18:00"]},
...         {"city": ["Toronto", "Berlin", "Paris"]},
...     ]
... ).dimensions
['hour', 'city']

dimensions_unsafe property

Same as dimensions but returns an empty list if there are no dimensions instead of None. When unsure, use dimensions instead since the type checker forces users to handle the None case (no dimensions).

friendly_name property

name = None instance-attribute

shape property

The number of indices in each dimension.

Examples:

>>> # A variable with no dimensions
>>> pf.Variable().shape
{}
>>> # A variable with dimensions of "hour" and "city"
>>> pf.Variable(
...     [
...         {"hour": ["00:00", "06:00", "12:00", "18:00"]},
...         {"city": ["Toronto", "Berlin", "Paris"]},
...     ]
... ).shape
{'hour': 4, 'city': 3}

__len__()

Source code in pyoframe/model_element.py
def __len__(self) -> int:
    dims = self.dimensions
    if dims is None:
        return 1
    return self.data.select(dims).n_unique()

on_add_to_model(model, name)

Source code in pyoframe/model_element.py
def on_add_to_model(self, model: "Model", name: str):
    self.name = name
    self._model = model

ModelElementWithId(data, **kwargs)

Bases: ModelElement

Provides a method that assigns a unique ID to each row in a DataFrame. IDs start at 1 and go up consecutively. No zero ID is assigned since it is reserved for the constant variable term. IDs are only unique for the subclass since different subclasses have different counters.

Methods:

Name Description
get_id_column_name

Returns the name of the column containing the IDs.

Source code in pyoframe/model_element.py
def __init__(self, data: pl.DataFrame, **kwargs) -> None:
    # Sanity checks, no duplicate column names
    assert len(data.columns) == len(set(data.columns)), (
        "Duplicate column names found."
    )

    cols = _get_dimensions(data)
    if cols is None:
        cols = []
    cols += [col for col in RESERVED_COL_KEYS if col in data.columns]

    # Reorder columns to keep things consistent
    data = data.select(cols)

    # Cast to proper dtype
    if COEF_KEY in data.columns:
        data = data.cast({COEF_KEY: pl.Float64})
    if VAR_KEY in data.columns:
        data = data.cast({VAR_KEY: KEY_TYPE})
    if QUAD_VAR_KEY in data.columns:
        data = data.cast({QUAD_VAR_KEY: KEY_TYPE})

    self._data = data
    self._model: Optional[Model] = None
    self.name = None
    super().__init__(**kwargs)

get_id_column_name() abstractmethod classmethod

Returns the name of the column containing the IDs.

Source code in pyoframe/model_element.py
@classmethod
@abstractmethod
def get_id_column_name(cls) -> str:
    """
    Returns the name of the column containing the IDs.
    """

SupportPolarsMethodMixin

Bases: ABC

Methods:

Name Description
pick

Filters elements by the given criteria and then drops the filtered dimensions.

Attributes:

Name Type Description
data
estimated_size
filter
rename
with_columns

data abstractmethod property

estimated_size = _support_polars_method('estimated_size') class-attribute instance-attribute

filter = _support_polars_method('filter') class-attribute instance-attribute

rename = _support_polars_method('rename') class-attribute instance-attribute

with_columns = _support_polars_method('with_columns') class-attribute instance-attribute

pick(**kwargs)

Filters elements by the given criteria and then drops the filtered dimensions.

Examples:

>>> m = pf.Model()
>>> m.v = pf.Variable(
...     [
...         {"hour": ["00:00", "06:00", "12:00", "18:00"]},
...         {"city": ["Toronto", "Berlin", "Paris"]},
...     ]
... )
>>> m.v.pick(hour="06:00")
<Expression size=3 dimensions={'city': 3} terms=3>
[Toronto]: v[06:00,Toronto]
[Berlin]: v[06:00,Berlin]
[Paris]: v[06:00,Paris]
>>> m.v.pick(hour="06:00", city="Toronto")
<Expression size=1 dimensions={} terms=1>
v[06:00,Toronto]
Source code in pyoframe/model_element.py
def pick(self, **kwargs):
    """
    Filters elements by the given criteria and then drops the filtered dimensions.

    Examples:
        >>> m = pf.Model()
        >>> m.v = pf.Variable(
        ...     [
        ...         {"hour": ["00:00", "06:00", "12:00", "18:00"]},
        ...         {"city": ["Toronto", "Berlin", "Paris"]},
        ...     ]
        ... )
        >>> m.v.pick(hour="06:00")
        <Expression size=3 dimensions={'city': 3} terms=3>
        [Toronto]: v[06:00,Toronto]
        [Berlin]: v[06:00,Berlin]
        [Paris]: v[06:00,Paris]
        >>> m.v.pick(hour="06:00", city="Toronto")
        <Expression size=1 dimensions={} terms=1>
        v[06:00,Toronto]
    """
    return self._new(self.data.filter(**kwargs).drop(kwargs.keys()))