Reverse the codes_to_groupby to account for sort / observed.

    Parameters
    ----------
    c : Categorical
    sort : boolean
        The value of the sort parameter groupby was called with.
    ci : CategoricalIndex
        The codes / categories to recode

    Returns
    -------
    CategoricalIndex

def recode_from_groupby(c, sort, ci):
    """
    Reverse the codes_to_groupby to account for sort / observed.

    Parameters
    ----------
    c : Categorical
    sort : boolean
        The value of the sort parameter groupby was called with.
    ci : CategoricalIndex
        The codes / categories to recode

    Returns
    -------
    CategoricalIndex
    """

    # we re-order to the original category orderings
    if sort:
        return ci.set_categories(c.categories)

    # we are not sorting, so add unobserved to the end
    return ci.add_categories(
        c.categories[~c.categories.isin(ci.categories)])