def assert_index_equal(left, right, exact='equiv', check_names=True,
                       check_less_precise=False, check_exact=True,
                       obj='Index'):
    """Check that left and right Index are equal.

    Parameters
    ----------
    left : Index
    right : Index
    exact : bool / string {'equiv'}, default False
        Whether to check the Index class, dtype and inferred_type
        are identical. If 'equiv', then RangeIndex can be substitued for
        Int64Index as well
    check_names : bool, default True
        Whether to check the names attribute.
    check_less_precise : bool, default False
        Specify comparison precision. Only used when check_exact is False.
        5 digits (False) or 3 digits (True) after decimal points are compared.
    check_exact : bool, default True
        Whether to compare number exactly.
    obj : str, default 'Index'
        Specify object name being compared, internally used to show appropriate
        assertion message
    """

    def _check_types(l, r, obj='Index'):
        if exact:

            if exact == 'equiv':
                if type(l) != type(r):
                    # allow equivalence of Int64Index/RangeIndex
                    types = set([type(l).__name__, type(r).__name__])
                    if len(types - set(['Int64Index', 'RangeIndex'])):
                        msg = '{0} classes are not equivalent'.format(obj)
                        raise_assert_detail(obj, msg, l, r)
            else:
                if type(l) != type(r):
                    msg = '{0} classes are different'.format(obj)
                    raise_assert_detail(obj, msg, l, r)

            assert_attr_equal('dtype', l, r, obj=obj)

            # allow string-like to have different inferred_types
            if l.inferred_type in ('string', 'unicode'):
                assertIn(r.inferred_type, ('string', 'unicode'))
            else:
                assert_attr_equal('inferred_type', l, r, obj=obj)

    def _get_ilevel_values(index, level):
        # accept level number only
        unique = index.levels[level]
        labels = index.labels[level]
        filled = take_1d(unique.values, labels, fill_value=unique._na_value)
        values = unique._simple_new(filled,
                                    name=index.names[level],
                                    freq=getattr(unique, 'freq', None),
                                    tz=getattr(unique, 'tz', None))
        return values

    # instance validation
    assertIsInstance(left, Index, '[index] ')
    assertIsInstance(right, Index, '[index] ')

    # class / dtype comparison
    _check_types(left, right, obj=obj)

    # level comparison
    if left.nlevels != right.nlevels:
        raise_assert_detail(obj, '{0} levels are different'.format(obj),
                            '{0}, {1}'.format(left.nlevels, left),
                            '{0}, {1}'.format(right.nlevels, right))

    # length comparison
    if len(left) != len(right):
        raise_assert_detail(obj, '{0} length are different'.format(obj),
                            '{0}, {1}'.format(len(left), left),
                            '{0}, {1}'.format(len(right), right))

    # MultiIndex special comparison for little-friendly error messages
    if left.nlevels > 1:
        for level in range(left.nlevels):
            # cannot use get_level_values here because it can change dtype
            llevel = _get_ilevel_values(left, level)
            rlevel = _get_ilevel_values(right, level)

            lobj = 'MultiIndex level [{0}]'.format(level)
            assert_index_equal(llevel, rlevel,
                               exact=exact, check_names=check_names,
                               check_less_precise=check_less_precise,
                               check_exact=check_exact, obj=lobj)
            # get_level_values may change dtype
            _check_types(left.levels[level], right.levels[level], obj=obj)

    if check_exact:
        if not left.equals(right):
            diff = np.sum((left.values != right.values)
                          .astype(int)) * 100.0 / len(left)
            msg = '{0} values are different ({1} %)'\
                .format(obj, np.round(diff, 5))
            raise_assert_detail(obj, msg, left, right)
    else:
        _testing.assert_almost_equal(left.values, right.values,
                                     check_less_precise=check_less_precise,
                                     obj=obj, lobj=left, robj=right)

    # metadata comparison
    if check_names:
        assert_attr_equal('names', left, right, obj=obj)
dataset/ETHPy150Open pydata/pandas/pandas/util/testing.py/assert_index_equal/original