def normalize_entity(self, base_entity_id, new_entity_id, index, additional_variables=None, copy_variables=None, make_time_index=None, make_secondary_time_index=None, new_entity_time_index=None, new_entity_secondary_time_index=None):
    'Create a new entity and relationship from unique values of an existing variable.\n\n        Args:\n            base_entity_id (str) : Entity id from which to split.\n\n            new_entity_id (str): Id of the new entity.\n\n            index (str): Variable in old entity\n                that will become index of new entity. Relationship\n                will be created across this variable.\n\n            additional_variables (list[str]):\n                List of variable ids to remove from\n                base_entity and move to new entity.\n\n            copy_variables (list[str]): List of\n                variable ids to copy from old entity\n                and move to new entity.\n\n            make_time_index (bool or str, optional): Create time index for new entity based\n                on time index in base_entity, optionally specifying which variable in base_entity\n                to use for time_index. If specified as True without a specific variable,\n                uses the primary time index. Defaults to True if base entity has a time index.\n\n            make_secondary_time_index (dict[str -> list[str]], optional): Create a secondary time index\n                from key. Values of dictionary\n                are the variables to associate with the secondary time index. Only one\n                secondary time index is allowed. If None, only associate the time index.\n\n            new_entity_time_index (str, optional): Rename new entity time index.\n\n            new_entity_secondary_time_index (str, optional): Rename new entity secondary time index.\n\n        '
    base_entity = self.entity_dict[base_entity_id]
    additional_variables = (additional_variables or [])
    copy_variables = (copy_variables or [])
    if (base_entity.time_index is not None):
        t_index = base_entity[base_entity.time_index]
        if (not isinstance(t_index, (vtypes.NumericTimeIndex, vtypes.DatetimeTimeIndex))):
            base_error = "Time index '{0}' is not a NumericTimeIndex or DatetimeTimeIndex, but type {1}. Use set_time_index on entity '{2}' to set the time_index."
            raise TypeError(base_error.format(base_entity.time_index, type(t_index), str(base_entity.id)))
    if (not isinstance(additional_variables, list)):
        raise TypeError("'additional_variables' must be a list, but received type {}".format(type(additional_variables)))
    if (len(additional_variables) != len(set(additional_variables))):
        raise ValueError("'additional_variables' contains duplicate variables. All variables must be unique.")
    if (not isinstance(copy_variables, list)):
        raise TypeError("'copy_variables' must be a list, but received type {}".format(type(copy_variables)))
    if (len(copy_variables) != len(set(copy_variables))):
        raise ValueError("'copy_variables' contains duplicate variables. All variables must be unique.")
    for v in (additional_variables + copy_variables):
        if (v == index):
            raise ValueError('Not copying {} as both index and variable'.format(v))
    for v in additional_variables:
        if (v == base_entity.time_index):
            raise ValueError('Not moving {} as it is the base time index variable. Perhaps, move the variable to the copy_variables.'.format(v))
    if isinstance(make_time_index, str):
        if (make_time_index not in base_entity.df.columns):
            raise ValueError("'make_time_index' must be a variable in the base entity")
        elif (make_time_index not in (additional_variables + copy_variables)):
            raise ValueError("'make_time_index' must be specified in 'additional_variables' or 'copy_variables'")
    if (index == base_entity.index):
        raise ValueError("'index' must be different from the index column of the base entity")
    transfer_types = {}
    transfer_types[index] = type(base_entity[index])
    for v in (additional_variables + copy_variables):
        if (type(base_entity[v]) == vtypes.DatetimeTimeIndex):
            transfer_types[v] = vtypes.Datetime
        elif (type(base_entity[v]) == vtypes.NumericTimeIndex):
            transfer_types[v] = vtypes.Numeric
        else:
            transfer_types[v] = type(base_entity[v])
    new_entity_df = self[base_entity_id].df.copy()
    if ((make_time_index is None) and (base_entity.time_index is not None)):
        make_time_index = True
    if isinstance(make_time_index, str):
        base_time_index = make_time_index
        new_entity_time_index = make_time_index
        already_sorted = (new_entity_time_index == base_entity.time_index)
    elif make_time_index:
        base_time_index = base_entity.time_index
        if (new_entity_time_index is None):
            new_entity_time_index = ('first_%s_time' % base_entity.id)
        already_sorted = True
        assert (base_entity.time_index is not None), "Base entity doesn't have time_index defined"
        if (base_time_index not in [v for v in additional_variables]):
            copy_variables.append(base_time_index)
        transfer_types[new_entity_time_index] = type(base_entity[base_entity.time_index])
    else:
        new_entity_time_index = None
        already_sorted = False
    if ((new_entity_time_index is not None) and (new_entity_time_index == index)):
        raise ValueError(('time_index and index cannot be the same value, %s' % new_entity_time_index))
    selected_variables = (([index] + [v for v in additional_variables]) + [v for v in copy_variables])
    new_entity_df2 = new_entity_df.drop_duplicates(index, keep='first')[selected_variables]
    if make_time_index:
        new_entity_df2 = new_entity_df2.rename(columns={base_time_index: new_entity_time_index})
    if make_secondary_time_index:
        assert (len(make_secondary_time_index) == 1), 'Can only provide 1 secondary time index'
        secondary_time_index = list(make_secondary_time_index.keys())[0]
        secondary_variables = ([index, secondary_time_index] + list(make_secondary_time_index.values())[0])
        secondary_df = new_entity_df.drop_duplicates(index, keep='last')[secondary_variables]
        if new_entity_secondary_time_index:
            secondary_df = secondary_df.rename(columns={secondary_time_index: new_entity_secondary_time_index})
            secondary_time_index = new_entity_secondary_time_index
        else:
            new_entity_secondary_time_index = secondary_time_index
        secondary_df = secondary_df.set_index(index)
        new_entity_df = new_entity_df2.join(secondary_df, on=index)
    else:
        new_entity_df = new_entity_df2
    base_entity_index = index
    transfer_types[index] = vtypes.Categorical
    if make_secondary_time_index:
        old_ti_name = list(make_secondary_time_index.keys())[0]
        ti_cols = list(make_secondary_time_index.values())[0]
        ti_cols = [(c if (c != old_ti_name) else secondary_time_index) for c in ti_cols]
        make_secondary_time_index = {secondary_time_index: ti_cols}
    self.entity_from_dataframe(new_entity_id, new_entity_df, index, already_sorted=already_sorted, time_index=new_entity_time_index, secondary_time_index=make_secondary_time_index, variable_types=transfer_types)
    self.entity_dict[base_entity_id].delete_variables(additional_variables)
    new_entity = self.entity_dict[new_entity_id]
    base_entity.convert_variable_type(base_entity_index, vtypes.Id, convert_data=False)
    self.add_relationship(Relationship(new_entity[index], base_entity[base_entity_index]))
    self.reset_data_description()
    return self
Create a new entity and relationship from unique values of an existing variable.

Args:
    base_entity_id (str) : Entity id from which to split.

    new_entity_id (str): Id of the new entity.

    index (str): Variable in old entity
        that will become index of new entity. Relationship
        will be created across this variable.

    additional_variables (list[str]):
        List of variable ids to remove from
        base_entity and move to new entity.

    copy_variables (list[str]): List of
        variable ids to copy from old entity
        and move to new entity.

    make_time_index (bool or str, optional): Create time index for new entity based
        on time index in base_entity, optionally specifying which variable in base_entity
        to use for time_index. If specified as True without a specific variable,
        uses the primary time index. Defaults to True if base entity has a time index.

    make_secondary_time_index (dict[str -> list[str]], optional): Create a secondary time index
        from key. Values of dictionary
        are the variables to associate with the secondary time index. Only one
        secondary time index is allowed. If None, only associate the time index.

    new_entity_time_index (str, optional): Rename new entity time index.

    new_entity_secondary_time_index (str, optional): Rename new entity secondary time index.
def normalize_entity(self, base_entity_id, new_entity_id, index, additional_variables=None, copy_variables=None, make_time_index=None, make_secondary_time_index=None, new_entity_time_index=None, new_entity_secondary_time_index=None):
    'Create a new entity and relationship from unique values of an existing variable.\n\n        Args:\n            base_entity_id (str) : Entity id from which to split.\n\n            new_entity_id (str): Id of the new entity.\n\n            index (str): Variable in old entity\n                that will become index of new entity. Relationship\n                will be created across this variable.\n\n            additional_variables (list[str]):\n                List of variable ids to remove from\n                base_entity and move to new entity.\n\n            copy_variables (list[str]): List of\n                variable ids to copy from old entity\n                and move to new entity.\n\n            make_time_index (bool or str, optional): Create time index for new entity based\n                on time index in base_entity, optionally specifying which variable in base_entity\n                to use for time_index. If specified as True without a specific variable,\n                uses the primary time index. Defaults to True if base entity has a time index.\n\n            make_secondary_time_index (dict[str -> list[str]], optional): Create a secondary time index\n                from key. Values of dictionary\n                are the variables to associate with the secondary time index. Only one\n                secondary time index is allowed. If None, only associate the time index.\n\n            new_entity_time_index (str, optional): Rename new entity time index.\n\n            new_entity_secondary_time_index (str, optional): Rename new entity secondary time index.\n\n        '
    base_entity = self.entity_dict[base_entity_id]
    additional_variables = (additional_variables or [])
    copy_variables = (copy_variables or [])
    if (base_entity.time_index is not None):
        t_index = base_entity[base_entity.time_index]
        if (not isinstance(t_index, (vtypes.NumericTimeIndex, vtypes.DatetimeTimeIndex))):
            base_error = "Time index '{0}' is not a NumericTimeIndex or DatetimeTimeIndex, but type {1}. Use set_time_index on entity '{2}' to set the time_index."
            raise TypeError(base_error.format(base_entity.time_index, type(t_index), str(base_entity.id)))
    if (not isinstance(additional_variables, list)):
        raise TypeError("'additional_variables' must be a list, but received type {}".format(type(additional_variables)))
    if (len(additional_variables) != len(set(additional_variables))):
        raise ValueError("'additional_variables' contains duplicate variables. All variables must be unique.")
    if (not isinstance(copy_variables, list)):
        raise TypeError("'copy_variables' must be a list, but received type {}".format(type(copy_variables)))
    if (len(copy_variables) != len(set(copy_variables))):
        raise ValueError("'copy_variables' contains duplicate variables. All variables must be unique.")
    for v in (additional_variables + copy_variables):
        if (v == index):
            raise ValueError('Not copying {} as both index and variable'.format(v))
    for v in additional_variables:
        if (v == base_entity.time_index):
            raise ValueError('Not moving {} as it is the base time index variable. Perhaps, move the variable to the copy_variables.'.format(v))
    if isinstance(make_time_index, str):
        if (make_time_index not in base_entity.df.columns):
            raise ValueError("'make_time_index' must be a variable in the base entity")
        elif (make_time_index not in (additional_variables + copy_variables)):
            raise ValueError("'make_time_index' must be specified in 'additional_variables' or 'copy_variables'")
    if (index == base_entity.index):
        raise ValueError("'index' must be different from the index column of the base entity")
    transfer_types = {}
    transfer_types[index] = type(base_entity[index])
    for v in (additional_variables + copy_variables):
        if (type(base_entity[v]) == vtypes.DatetimeTimeIndex):
            transfer_types[v] = vtypes.Datetime
        elif (type(base_entity[v]) == vtypes.NumericTimeIndex):
            transfer_types[v] = vtypes.Numeric
        else:
            transfer_types[v] = type(base_entity[v])
    new_entity_df = self[base_entity_id].df.copy()
    if ((make_time_index is None) and (base_entity.time_index is not None)):
        make_time_index = True
    if isinstance(make_time_index, str):
        base_time_index = make_time_index
        new_entity_time_index = make_time_index
        already_sorted = (new_entity_time_index == base_entity.time_index)
    elif make_time_index:
        base_time_index = base_entity.time_index
        if (new_entity_time_index is None):
            new_entity_time_index = ('first_%s_time' % base_entity.id)
        already_sorted = True
        assert (base_entity.time_index is not None), "Base entity doesn't have time_index defined"
        if (base_time_index not in [v for v in additional_variables]):
            copy_variables.append(base_time_index)
        transfer_types[new_entity_time_index] = type(base_entity[base_entity.time_index])
    else:
        new_entity_time_index = None
        already_sorted = False
    if ((new_entity_time_index is not None) and (new_entity_time_index == index)):
        raise ValueError(('time_index and index cannot be the same value, %s' % new_entity_time_index))
    selected_variables = (([index] + [v for v in additional_variables]) + [v for v in copy_variables])
    new_entity_df2 = new_entity_df.drop_duplicates(index, keep='first')[selected_variables]
    if make_time_index:
        new_entity_df2 = new_entity_df2.rename(columns={base_time_index: new_entity_time_index})
    if make_secondary_time_index:
        assert (len(make_secondary_time_index) == 1), 'Can only provide 1 secondary time index'
        secondary_time_index = list(make_secondary_time_index.keys())[0]
        secondary_variables = ([index, secondary_time_index] + list(make_secondary_time_index.values())[0])
        secondary_df = new_entity_df.drop_duplicates(index, keep='last')[secondary_variables]
        if new_entity_secondary_time_index:
            secondary_df = secondary_df.rename(columns={secondary_time_index: new_entity_secondary_time_index})
            secondary_time_index = new_entity_secondary_time_index
        else:
            new_entity_secondary_time_index = secondary_time_index
        secondary_df = secondary_df.set_index(index)
        new_entity_df = new_entity_df2.join(secondary_df, on=index)
    else:
        new_entity_df = new_entity_df2
    base_entity_index = index
    transfer_types[index] = vtypes.Categorical
    if make_secondary_time_index:
        old_ti_name = list(make_secondary_time_index.keys())[0]
        ti_cols = list(make_secondary_time_index.values())[0]
        ti_cols = [(c if (c != old_ti_name) else secondary_time_index) for c in ti_cols]
        make_secondary_time_index = {secondary_time_index: ti_cols}
    self.entity_from_dataframe(new_entity_id, new_entity_df, index, already_sorted=already_sorted, time_index=new_entity_time_index, secondary_time_index=make_secondary_time_index, variable_types=transfer_types)
    self.entity_dict[base_entity_id].delete_variables(additional_variables)
    new_entity = self.entity_dict[new_entity_id]
    base_entity.convert_variable_type(base_entity_index, vtypes.Id, convert_data=False)
    self.add_relationship(Relationship(new_entity[index], base_entity[base_entity_index]))
    self.reset_data_description()
    return self