Dataframe group-by operation that supports aggregating by different methods on the index.

    Parameters
    ----------
    df: ``DataFrame``
        Pandas dataframe with a MultiIndex
    grouping_level: ``int`` or ``str`` or ``list`` of ``str``
        Index level to group by. Defaults to 0.
    aggregate_level: ``int`` or ``str``
        Index level to aggregate by. Defaults to 1.
    method: ``str``
        Aggregation method. One of
            last: Use the last (lexicographically) value from each group
            first: Use the first value from each group
    max_: <any>
        If set, will limit results to those having aggregate level values <= this value
    min_: <any>
        If set, will limit results to those having aggregate level values >= this value
    within: Any type supported by the index, or ``DateOffset``/timedelta-like for ``DatetimeIndex``.
        If set, will limit results to those having aggregate level values within this range of the group value.
        Note that this is currently unsupported for Multi-index of depth > 2

def fancy_group_by(df, grouping_level=0, aggregate_level=1, method='last', max_=None, min_=None, within=None):
    """ Dataframe group-by operation that supports aggregating by different methods on the index.

    Parameters
    ----------
    df: ``DataFrame``
        Pandas dataframe with a MultiIndex
    grouping_level: ``int`` or ``str`` or ``list`` of ``str``
        Index level to group by. Defaults to 0.
    aggregate_level: ``int`` or ``str``
        Index level to aggregate by. Defaults to 1.
    method: ``str``
        Aggregation method. One of
            last: Use the last (lexicographically) value from each group
            first: Use the first value from each group
    max_: <any>
        If set, will limit results to those having aggregate level values <= this value
    min_: <any>
        If set, will limit results to those having aggregate level values >= this value
    within: Any type supported by the index, or ``DateOffset``/timedelta-like for ``DatetimeIndex``.
        If set, will limit results to those having aggregate level values within this range of the group value.
        Note that this is currently unsupported for Multi-index of depth > 2
    """
    if method not in ('first', 'last'):
        raise ValueError('Invalid method')

    if isinstance(aggregate_level, six.string_types):
        aggregate_level = df.index.names.index(aggregate_level)

    # Trim any rows outside the aggregate value bounds
    if max_ is not None or min_ is not None or within is not None:
        agg_idx = df.index.get_level_values(aggregate_level)
        mask = np.full(len(agg_idx), True, dtype='b1')
        if max_ is not None:
            mask &= (agg_idx <= max_)
        if min_ is not None:
            mask &= (agg_idx >= min_)
        if within is not None:
            group_idx = df.index.get_level_values(grouping_level)
            if isinstance(agg_idx, pd.DatetimeIndex):
                mask &= (group_idx >= agg_idx.shift(-1, freq=within))
            else:
                mask &= (group_idx >= (agg_idx - within))
        df = df.loc[mask]

    # The sort order must be correct in order of grouping_level -> aggregate_level for the aggregation methods
    # to work properly. We can check the sortdepth to see if this is in fact the case and resort if necessary.
    # TODO: this might need tweaking if the levels are around the wrong way
    if df.index.lexsort_depth < (aggregate_level + 1):
        df = df.sort_index(level=grouping_level)

    gb = df.groupby(level=grouping_level)
    if method == 'last':
        return gb.last()
    return gb.first()