Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

DEPR: Deprecate passing range-like arguments to DatetimeIndex, TimedeltaIndex #23919

Merged
merged 21 commits into from
Nov 28, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
21 commits
Select commit Hold shift + click to select a range
f8bed85
Deprecate passing range-like arguments to DatetimeIndex, TimedeltaIndex
jbrockmendel Nov 26, 2018
5d8a107
GH reference
jbrockmendel Nov 26, 2018
28e2184
Merge branch 'master' of https://github.com/pandas-dev/pandas into ge…
jbrockmendel Nov 26, 2018
0f75b9d
Flake8 fixups, whatsnew typo
jbrockmendel Nov 26, 2018
2c40c3a
update usage in resample
jbrockmendel Nov 26, 2018
d67f87c
Merge branch 'master' of https://github.com/pandas-dev/pandas into ge…
jbrockmendel Nov 26, 2018
afdab5b
targeted tests
jbrockmendel Nov 26, 2018
8f435ed
backticks
jbrockmendel Nov 26, 2018
4d7c9e2
test the right thing
jbrockmendel Nov 26, 2018
2e587e3
avoid verify_integrity warnings
jbrockmendel Nov 26, 2018
0469b74
avoid verify_integrity
jbrockmendel Nov 26, 2018
43a52fc
isort
jbrockmendel Nov 26, 2018
f4e281e
Merge branch 'master' of https://github.com/pandas-dev/pandas into ge…
jbrockmendel Nov 27, 2018
15e6c30
change default to None
jbrockmendel Nov 27, 2018
5dc66f3
set verify_integrity conditionally
jbrockmendel Nov 27, 2018
b931878
Merge branch 'master' of https://github.com/pandas-dev/pandas into ge…
jbrockmendel Nov 27, 2018
07bfc45
Merge branch 'master' of https://github.com/pandas-dev/pandas into ge…
jbrockmendel Nov 27, 2018
e209a81
Merge branch 'master' of https://github.com/pandas-dev/pandas into ge…
jbrockmendel Nov 28, 2018
d6df7a3
Merge branch 'master' of https://github.com/pandas-dev/pandas into ge…
jbrockmendel Nov 28, 2018
eb5d9c5
Merge branch 'master' of https://github.com/pandas-dev/pandas into ge…
jbrockmendel Nov 28, 2018
cc40717
restore edit that got lost in rebase
jbrockmendel Nov 28, 2018
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

you can check __reduce__, d should be _data and the attributes dict

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

good idea, that seems to work; just pushed

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks like this broke the legacy pickle tests; reverted.

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 @@ -1514,9 +1530,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 @@ -1602,9 +1622,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 @@ -1661,9 +1681,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 @@ -735,5 +746,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
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

not important, but was just wondering: why are you adding the '#' everywhere?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Mostly for internal consistency (not a big deal, but for grepping purposes). A little bit because I was curious how long it would take before someone asked about it.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

we have have the gh-xxxx style as well, slight prefernce for that

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