Skip to content

Commit

Permalink
DEPR: Deprecate passing range-like arguments to DatetimeIndex, Timede…
Browse files Browse the repository at this point in the history
…ltaIndex (pandas-dev#23919)
  • Loading branch information
jbrockmendel authored and Pingviinituutti committed Feb 28, 2019
1 parent 33d9086 commit 122fa0c
Show file tree
Hide file tree
Showing 38 changed files with 266 additions and 212 deletions.
1 change: 1 addition & 0 deletions doc/source/whatsnew/v0.24.0.rst
Original file line number Diff line number Diff line change
Expand Up @@ -1076,6 +1076,7 @@ Deprecations
- Timezone converting a tz-aware ``datetime.datetime`` or :class:`Timestamp` with :class:`Timestamp` and the ``tz`` argument is now deprecated. Instead, use :meth:`Timestamp.tz_convert` (:issue:`23579`)
- :func:`pandas.types.is_period` is deprecated in favor of `pandas.types.is_period_dtype` (:issue:`23917`)
- :func:`pandas.types.is_datetimetz` is deprecated in favor of `pandas.types.is_datetime64tz` (:issue:`23917`)
- Creating a :class:`TimedeltaIndex` or :class:`DatetimeIndex` by passing range arguments `start`, `end`, and `periods` is deprecated in favor of :func:`timedelta_range` and :func:`date_range` (:issue:`23919`)

.. _whatsnew_0240.deprecations.datetimelike_int_ops:

Expand Down
49 changes: 35 additions & 14 deletions pandas/core/indexes/datetimes.py
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,13 @@ def _new_DatetimeIndex(cls, d):
# so need to localize
tz = d.pop('tz', None)

result = cls.__new__(cls, verify_integrity=False, **d)
with warnings.catch_warnings():
# we ignore warnings from passing verify_integrity=False
# TODO: If we knew what was going in to **d, we might be able to
# go through _simple_new instead
warnings.simplefilter("ignore")
result = cls.__new__(cls, verify_integrity=False, **d)

if tz is not None:
result = result.tz_localize('UTC').tz_convert(tz)
return result
Expand Down Expand Up @@ -220,10 +226,20 @@ def __new__(cls, data=None,
freq=None, start=None, end=None, periods=None, tz=None,
normalize=False, closed=None, ambiguous='raise',
dayfirst=False, yearfirst=False, dtype=None,
copy=False, name=None, verify_integrity=True):
copy=False, name=None, verify_integrity=None):

if verify_integrity is not None:
warnings.warn("The 'verify_integrity' argument is deprecated, "
"will be removed in a future version.",
FutureWarning, stacklevel=2)
else:
verify_integrity = True

if data is None:
# TODO: Remove this block and associated kwargs; GH#20535
warnings.warn("Creating a DatetimeIndex by passing range "
"endpoints is deprecated. Use "
"`pandas.date_range` instead.",
FutureWarning, stacklevel=2)
result = cls._generate_range(start, end, periods,
freq=freq, tz=tz, normalize=normalize,
closed=closed, ambiguous=ambiguous)
Expand Down Expand Up @@ -756,8 +772,8 @@ def snap(self, freq='S'):
snapped[i] = s

# we know it conforms; skip check
return DatetimeIndex(snapped, freq=freq, verify_integrity=False)
# TODO: what about self.name? if so, use shallow_copy?
return DatetimeIndex._simple_new(snapped, freq=freq)
# TODO: what about self.name? tz? if so, use shallow_copy?

def unique(self, level=None):
if level is not None:
Expand Down Expand Up @@ -1519,9 +1535,13 @@ def date_range(start=None, end=None, periods=None, freq=None, tz=None,
if freq is None and com._any_none(periods, start, end):
freq = 'D'

return DatetimeIndex(start=start, end=end, periods=periods,
freq=freq, tz=tz, normalize=normalize, name=name,
closed=closed, **kwargs)
result = DatetimeIndex._generate_range(
start=start, end=end, periods=periods,
freq=freq, tz=tz, normalize=normalize,
closed=closed, **kwargs)

result.name = name
return result


def bdate_range(start=None, end=None, periods=None, freq='B', tz=None,
Expand Down Expand Up @@ -1607,9 +1627,9 @@ def bdate_range(start=None, end=None, periods=None, freq='B', tz=None,
'weekmask are passed, got frequency {freq}').format(freq=freq)
raise ValueError(msg)

return DatetimeIndex(start=start, end=end, periods=periods,
freq=freq, tz=tz, normalize=normalize, name=name,
closed=closed, **kwargs)
return date_range(start=start, end=end, periods=periods,
freq=freq, tz=tz, normalize=normalize, name=name,
closed=closed, **kwargs)


def cdate_range(start=None, end=None, periods=None, freq='C', tz=None,
Expand Down Expand Up @@ -1666,9 +1686,10 @@ def cdate_range(start=None, end=None, periods=None, freq='C', tz=None,
holidays = kwargs.pop('holidays', [])
weekmask = kwargs.pop('weekmask', 'Mon Tue Wed Thu Fri')
freq = CDay(holidays=holidays, weekmask=weekmask)
return DatetimeIndex(start=start, end=end, periods=periods, freq=freq,
tz=tz, normalize=normalize, name=name,
closed=closed, **kwargs)

return date_range(start=start, end=end, periods=periods, freq=freq,
tz=tz, normalize=normalize, name=name,
closed=closed, **kwargs)


def _time_to_micros(time):
Expand Down
22 changes: 18 additions & 4 deletions pandas/core/indexes/timedeltas.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
""" implement the TimedeltaIndex """
from datetime import datetime
import warnings

import numpy as np

Expand Down Expand Up @@ -132,12 +133,22 @@ def _join_i8_wrapper(joinf, **kwargs):

def __new__(cls, data=None, unit=None, freq=None, start=None, end=None,
periods=None, closed=None, dtype=None, copy=False,
name=None, verify_integrity=True):
name=None, verify_integrity=None):

if verify_integrity is not None:
warnings.warn("The 'verify_integrity' argument is deprecated, "
"will be removed in a future version.",
FutureWarning, stacklevel=2)
else:
verify_integrity = True

freq, freq_infer = dtl.maybe_infer_freq(freq)

if data is None:
# TODO: Remove this block and associated kwargs; GH#20535
warnings.warn("Creating a TimedeltaIndex by passing range "
"endpoints is deprecated. Use "
"`pandas.timedelta_range` instead.",
FutureWarning, stacklevel=2)
result = cls._generate_range(start, end, periods, freq,
closed=closed)
result.name = name
Expand Down Expand Up @@ -740,5 +751,8 @@ def timedelta_range(start=None, end=None, periods=None, freq=None,
if freq is None and com._any_none(periods, start, end):
freq = 'D'

return TimedeltaIndex(start=start, end=end, periods=periods,
freq=freq, name=name, closed=closed)
freq, freq_infer = dtl.maybe_infer_freq(freq)
result = TimedeltaIndex._generate_range(start, end, periods, freq,
closed=closed)
result.name = name
return result
20 changes: 10 additions & 10 deletions pandas/core/resample.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@
from pandas.core.groupby.ops import BinGrouper
from pandas.core.indexes.datetimes import DatetimeIndex, date_range
from pandas.core.indexes.period import PeriodIndex
from pandas.core.indexes.timedeltas import TimedeltaIndex
from pandas.core.indexes.timedeltas import TimedeltaIndex, timedelta_range

from pandas.tseries.frequencies import is_subperiod, is_superperiod, to_offset
from pandas.tseries.offsets import (
Expand Down Expand Up @@ -1398,11 +1398,11 @@ def _get_time_bins(self, ax):
# because replace() will swallow the nanosecond part
# thus last bin maybe slightly before the end if the end contains
# nanosecond part and lead to `Values falls after last bin` error
binner = labels = DatetimeIndex(freq=self.freq,
start=first,
end=last,
tz=tz,
name=ax.name)
binner = labels = date_range(freq=self.freq,
start=first,
end=last,
tz=tz,
name=ax.name)

# GH 15549
# In edge case of tz-aware resapmling binner last index can be
Expand Down Expand Up @@ -1484,10 +1484,10 @@ def _get_time_delta_bins(self, ax):
return binner, [], labels

start, end = ax.min(), ax.max()
labels = binner = TimedeltaIndex(start=start,
end=end,
freq=self.freq,
name=ax.name)
labels = binner = timedelta_range(start=start,
end=end,
freq=self.freq,
name=ax.name)

end_stamps = labels + self.freq
bins = ax.searchsorted(end_stamps, side='left')
Expand Down
4 changes: 2 additions & 2 deletions pandas/io/packers.py
Original file line number Diff line number Diff line change
Expand Up @@ -604,8 +604,8 @@ def decode(obj):

elif typ == u'datetime_index':
data = unconvert(obj[u'data'], np.int64, obj.get(u'compress'))
d = dict(name=obj[u'name'], freq=obj[u'freq'], verify_integrity=False)
result = globals()[obj[u'klass']](data, **d)
d = dict(name=obj[u'name'], freq=obj[u'freq'])
result = DatetimeIndex._simple_new(data, **d)
tz = obj[u'tz']

# reverse tz conversion
Expand Down
2 changes: 1 addition & 1 deletion pandas/tests/frame/test_indexing.py
Original file line number Diff line number Diff line change
Expand Up @@ -647,7 +647,7 @@ def test_setitem_boolean_column(self):

def test_frame_setitem_timestamp(self):
# GH#2155
columns = DatetimeIndex(start='1/1/2012', end='2/1/2012', freq=BDay())
columns = date_range(start='1/1/2012', end='2/1/2012', freq=BDay())
index = lrange(10)
data = DataFrame(columns=columns, index=index)
t = datetime(2012, 11, 1)
Expand Down
4 changes: 2 additions & 2 deletions pandas/tests/groupby/test_groupby.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@

from pandas import (date_range, Timestamp,
Index, MultiIndex, DataFrame, Series,
Panel, DatetimeIndex, read_csv)
Panel, read_csv)
from pandas.errors import PerformanceWarning
from pandas.util.testing import (assert_frame_equal,
assert_series_equal, assert_almost_equal)
Expand Down Expand Up @@ -1438,7 +1438,7 @@ def test_groupby_sort_multiindex_series():
def test_groupby_reindex_inside_function():

periods = 1000
ind = DatetimeIndex(start='2012/1/1', freq='5min', periods=periods)
ind = date_range(start='2012/1/1', freq='5min', periods=periods)
df = DataFrame({'high': np.arange(
periods), 'low': np.arange(periods)}, index=ind)

Expand Down
8 changes: 4 additions & 4 deletions pandas/tests/groupby/test_timegrouper.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@

import pandas as pd
from pandas import (DataFrame, date_range, Index,
Series, MultiIndex, Timestamp, DatetimeIndex)
Series, MultiIndex, Timestamp)
from pandas.core.groupby.ops import BinGrouper
from pandas.compat import StringIO
from pandas.util import testing as tm
Expand Down Expand Up @@ -374,9 +374,9 @@ def sumfunc_value(x):
expected.reset_index(drop=True))

def test_groupby_groups_datetimeindex(self):
# #1430
# GH#1430
periods = 1000
ind = DatetimeIndex(start='2012/1/1', freq='5min', periods=periods)
ind = pd.date_range(start='2012/1/1', freq='5min', periods=periods)
df = DataFrame({'high': np.arange(periods),
'low': np.arange(periods)}, index=ind)
grouped = df.groupby(lambda x: datetime(x.year, x.month, x.day))
Expand All @@ -385,7 +385,7 @@ def test_groupby_groups_datetimeindex(self):
groups = grouped.groups
assert isinstance(list(groups.keys())[0], datetime)

# GH 11442
# GH#11442
index = pd.date_range('2015/01/01', periods=5, name='date')
df = pd.DataFrame({'A': [5, 6, 7, 8, 9],
'B': [1, 2, 3, 4, 5]}, index=index)
Expand Down
59 changes: 35 additions & 24 deletions pandas/tests/indexes/datetimes/test_construction.py
Original file line number Diff line number Diff line change
Expand Up @@ -347,17 +347,28 @@ def test_construction_with_ndarray(self):
freq='B')
tm.assert_index_equal(result, expected)

def test_verify_integrity_deprecated(self):
# GH#23919
with tm.assert_produces_warning(FutureWarning):
DatetimeIndex(['1/1/2000'], verify_integrity=False)

def test_range_kwargs_deprecated(self):
# GH#23919
with tm.assert_produces_warning(FutureWarning):
DatetimeIndex(start='1/1/2000', end='1/10/2000', freq='D')

def test_constructor_coverage(self):
rng = date_range('1/1/2000', periods=10.5)
exp = date_range('1/1/2000', periods=10)
tm.assert_index_equal(rng, exp)

msg = 'periods must be a number, got foo'
with pytest.raises(TypeError, match=msg):
DatetimeIndex(start='1/1/2000', periods='foo', freq='D')
date_range(start='1/1/2000', periods='foo', freq='D')

pytest.raises(ValueError, DatetimeIndex, start='1/1/2000',
end='1/10/2000')
with pytest.raises(ValueError):
with tm.assert_produces_warning(FutureWarning):
DatetimeIndex(start='1/1/2000', end='1/10/2000')

with pytest.raises(TypeError):
DatetimeIndex('1/1/2000')
Expand Down Expand Up @@ -391,11 +402,11 @@ def test_constructor_coverage(self):
pytest.raises(ValueError, DatetimeIndex,
['2000-01-01', '2000-01-02', '2000-01-04'], freq='D')

pytest.raises(ValueError, DatetimeIndex, start='2011-01-01',
pytest.raises(ValueError, date_range, start='2011-01-01',
freq='b')
pytest.raises(ValueError, DatetimeIndex, end='2011-01-01',
pytest.raises(ValueError, date_range, end='2011-01-01',
freq='B')
pytest.raises(ValueError, DatetimeIndex, periods=10, freq='D')
pytest.raises(ValueError, date_range, periods=10, freq='D')

@pytest.mark.parametrize('freq', ['AS', 'W-SUN'])
def test_constructor_datetime64_tzformat(self, freq):
Expand Down Expand Up @@ -476,8 +487,8 @@ def test_constructor_dtype(self):
tm.assert_index_equal(idx, result)

def test_constructor_name(self):
idx = DatetimeIndex(start='2000-01-01', periods=1, freq='A',
name='TEST')
idx = date_range(start='2000-01-01', periods=1, freq='A',
name='TEST')
assert idx.name == 'TEST'

def test_000constructor_resolution(self):
Expand All @@ -500,7 +511,7 @@ def test_constructor_start_end_with_tz(self, tz):
# GH 18595
start = Timestamp('2013-01-01 06:00:00', tz='America/Los_Angeles')
end = Timestamp('2013-01-02 06:00:00', tz='America/Los_Angeles')
result = DatetimeIndex(freq='D', start=start, end=end, tz=tz)
result = date_range(freq='D', start=start, end=end, tz=tz)
expected = DatetimeIndex(['2013-01-01 06:00:00',
'2013-01-02 06:00:00'],
tz='America/Los_Angeles')
Expand Down Expand Up @@ -616,7 +627,7 @@ def test_ctor_str_intraday(self):
assert rng[0].second == 1

def test_is_(self):
dti = DatetimeIndex(start='1/1/2005', end='12/1/2005', freq='M')
dti = date_range(start='1/1/2005', end='12/1/2005', freq='M')
assert dti.is_(dti)
assert dti.is_(dti.view())
assert not dti.is_(dti.copy())
Expand Down Expand Up @@ -644,12 +655,12 @@ def test_constructor_int64_nocopy(self):
@pytest.mark.parametrize('freq', ['M', 'Q', 'A', 'D', 'B', 'BH',
'T', 'S', 'L', 'U', 'H', 'N', 'C'])
def test_from_freq_recreate_from_data(self, freq):
org = DatetimeIndex(start='2001/02/01 09:00', freq=freq, periods=1)
org = date_range(start='2001/02/01 09:00', freq=freq, periods=1)
idx = DatetimeIndex(org, freq=freq)
tm.assert_index_equal(idx, org)

org = DatetimeIndex(start='2001/02/01 09:00', freq=freq,
tz='US/Pacific', periods=1)
org = date_range(start='2001/02/01 09:00', freq=freq,
tz='US/Pacific', periods=1)
idx = DatetimeIndex(org, freq=freq, tz='US/Pacific')
tm.assert_index_equal(idx, org)

Expand Down Expand Up @@ -688,30 +699,30 @@ def test_datetimeindex_constructor_misc(self):

sdate = datetime(1999, 12, 25)
edate = datetime(2000, 1, 1)
idx = DatetimeIndex(start=sdate, freq='1B', periods=20)
idx = date_range(start=sdate, freq='1B', periods=20)
assert len(idx) == 20
assert idx[0] == sdate + 0 * offsets.BDay()
assert idx.freq == 'B'

idx = DatetimeIndex(end=edate, freq=('D', 5), periods=20)
idx = date_range(end=edate, freq=('D', 5), periods=20)
assert len(idx) == 20
assert idx[-1] == edate
assert idx.freq == '5D'

idx1 = DatetimeIndex(start=sdate, end=edate, freq='W-SUN')
idx2 = DatetimeIndex(start=sdate, end=edate,
freq=offsets.Week(weekday=6))
idx1 = date_range(start=sdate, end=edate, freq='W-SUN')
idx2 = date_range(start=sdate, end=edate,
freq=offsets.Week(weekday=6))
assert len(idx1) == len(idx2)
assert idx1.freq == idx2.freq

idx1 = DatetimeIndex(start=sdate, end=edate, freq='QS')
idx2 = DatetimeIndex(start=sdate, end=edate,
freq=offsets.QuarterBegin(startingMonth=1))
idx1 = date_range(start=sdate, end=edate, freq='QS')
idx2 = date_range(start=sdate, end=edate,
freq=offsets.QuarterBegin(startingMonth=1))
assert len(idx1) == len(idx2)
assert idx1.freq == idx2.freq

idx1 = DatetimeIndex(start=sdate, end=edate, freq='BQ')
idx2 = DatetimeIndex(start=sdate, end=edate,
freq=offsets.BQuarterEnd(startingMonth=12))
idx1 = date_range(start=sdate, end=edate, freq='BQ')
idx2 = date_range(start=sdate, end=edate,
freq=offsets.BQuarterEnd(startingMonth=12))
assert len(idx1) == len(idx2)
assert idx1.freq == idx2.freq
Loading

0 comments on commit 122fa0c

Please sign in to comment.