from __future__ import division from functools import partial import numpy as np import pytest from pandas.compat import lzip from pandas.core.dtypes.common import is_categorical_dtype from pandas.core.dtypes.dtypes import IntervalDtype from pandas import ( Categorical, CategoricalIndex, Float64Index, Index, Int64Index, Interval, IntervalIndex, date_range, notna, period_range, timedelta_range) from pandas.core.arrays import IntervalArray import pandas.core.common as com import pandas.util.testing as tm @pytest.fixture(params=[None, 'foo']) def name(request): return request.param class Base(object): """ Common tests for all variations of IntervalIndex construction. Input data to be supplied in breaks format, then converted by the subclass method get_kwargs_from_breaks to the expected format. """ @pytest.mark.parametrize('breaks', [ [3, 14, 15, 92, 653], np.arange(10, dtype='int64'), Int64Index(range(-10, 11)), Float64Index(np.arange(20, 30, 0.5)), date_range('20180101', periods=10), date_range('20180101', periods=10, tz='US/Eastern'), timedelta_range('1 day', periods=10)]) def test_constructor(self, constructor, breaks, closed, name): result_kwargs = self.get_kwargs_from_breaks(breaks, closed) result = constructor(closed=closed, name=name, **result_kwargs) assert result.closed == closed assert result.name == name assert result.dtype.subtype == getattr(breaks, 'dtype', 'int64') tm.assert_index_equal(result.left, Index(breaks[:-1])) tm.assert_index_equal(result.right, Index(breaks[1:])) @pytest.mark.parametrize('breaks, subtype', [ (Int64Index([0, 1, 2, 3, 4]), 'float64'), (Int64Index([0, 1, 2, 3, 4]), 'datetime64[ns]'), (Int64Index([0, 1, 2, 3, 4]), 'timedelta64[ns]'), (Float64Index([0, 1, 2, 3, 4]), 'int64'), (date_range('2017-01-01', periods=5), 'int64'), (timedelta_range('1 day', periods=5), 'int64')]) def test_constructor_dtype(self, constructor, breaks, subtype): # GH 19262: conversion via dtype parameter expected_kwargs = self.get_kwargs_from_breaks(breaks.astype(subtype)) expected = constructor(**expected_kwargs) result_kwargs = self.get_kwargs_from_breaks(breaks) iv_dtype = IntervalDtype(subtype) for dtype in (iv_dtype, str(iv_dtype)): result = constructor(dtype=dtype, **result_kwargs) tm.assert_index_equal(result, expected) @pytest.mark.parametrize('breaks', [ [np.nan] * 2, [np.nan] * 4, [np.nan] * 50]) def test_constructor_nan(self, constructor, breaks, closed): # GH 18421 result_kwargs = self.get_kwargs_from_breaks(breaks) result = constructor(closed=closed, **result_kwargs) expected_subtype = np.float64 expected_values = np.array(breaks[:-1], dtype=object) assert result.closed == closed assert result.dtype.subtype == expected_subtype tm.assert_numpy_array_equal(result._ndarray_values, expected_values) @pytest.mark.parametrize('breaks', [ [], np.array([], dtype='int64'), np.array([], dtype='float64'), np.array([], dtype='datetime64[ns]'), np.array([], dtype='timedelta64[ns]')]) def test_constructor_empty(self, constructor, breaks, closed): # GH 18421 result_kwargs = self.get_kwargs_from_breaks(breaks) result = constructor(closed=closed, **result_kwargs) expected_values = np.array([], dtype=object) expected_subtype = getattr(breaks, 'dtype', np.int64) assert result.empty assert result.closed == closed assert result.dtype.subtype == expected_subtype tm.assert_numpy_array_equal(result._ndarray_values, expected_values) @pytest.mark.parametrize('breaks', [ tuple('0123456789'), list('abcdefghij'), np.array(list('abcdefghij'), dtype=object), np.array(list('abcdefghij'), dtype=' with value 0 " "is not an interval") with pytest.raises(TypeError, match=msg): constructor([0, 1]) @pytest.mark.parametrize('data, closed', [ ([], 'both'), ([np.nan, np.nan], 'neither'), ([Interval(0, 3, closed='neither'), Interval(2, 5, closed='neither')], 'left'), ([Interval(0, 3, closed='left'), Interval(2, 5, closed='right')], 'neither'), (IntervalIndex.from_breaks(range(5), closed='both'), 'right')]) def test_override_inferred_closed(self, constructor, data, closed): # GH 19370 if isinstance(data, IntervalIndex): tuples = data.to_tuples() else: tuples = [(iv.left, iv.right) if notna(iv) else iv for iv in data] expected = IntervalIndex.from_tuples(tuples, closed=closed) result = constructor(data, closed=closed) tm.assert_index_equal(result, expected) @pytest.mark.parametrize('values_constructor', [ list, np.array, IntervalIndex, IntervalArray]) def test_index_object_dtype(self, values_constructor): # Index(intervals, dtype=object) is an Index (not an IntervalIndex) intervals = [Interval(0, 1), Interval(1, 2), Interval(2, 3)] values = values_constructor(intervals) result = Index(values, dtype=object) assert type(result) is Index tm.assert_numpy_array_equal(result.values, np.array(values)) class TestFromIntervals(TestClassConstructors): """ Tests for IntervalIndex.from_intervals, which is deprecated in favor of the IntervalIndex constructor. Same tests as the IntervalIndex constructor, plus deprecation test. Should only need to delete this class when removed. """ @pytest.fixture def constructor(self): def from_intervals_ignore_warnings(*args, **kwargs): with tm.assert_produces_warning(FutureWarning, check_stacklevel=False): return IntervalIndex.from_intervals(*args, **kwargs) return from_intervals_ignore_warnings def test_deprecated(self): ivs = [Interval(0, 1), Interval(1, 2)] with tm.assert_produces_warning(FutureWarning, check_stacklevel=False): IntervalIndex.from_intervals(ivs) @pytest.mark.skip(reason='parent class test that is not applicable') def test_index_object_dtype(self): pass