Skip to content

DEPR: Deprecate range-based PeriodIndex construction #24354

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

Merged
merged 13 commits into from
Dec 28, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
6 changes: 3 additions & 3 deletions asv_bench/benchmarks/period.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
from pandas import (DataFrame, Series, Period, PeriodIndex, date_range,
period_range)
from pandas import (
DataFrame, Period, PeriodIndex, Series, date_range, period_range)


class PeriodProperties(object):
Expand Down Expand Up @@ -94,7 +94,7 @@ def time_value_counts(self, typ):
class Indexing(object):

def setup(self):
self.index = PeriodIndex(start='1985', periods=1000, freq='D')
self.index = period_range(start='1985', periods=1000, freq='D')
self.series = Series(range(1000), index=self.index)
self.period = self.index[500]

Expand Down
4 changes: 2 additions & 2 deletions doc/source/whatsnew/v0.21.0.rst
Original file line number Diff line number Diff line change
Expand Up @@ -654,7 +654,7 @@ Previous Behavior:

.. code-block:: ipython

In [1]: pi = pd.PeriodIndex(start='2000-01-01', freq='D', periods=10)
In [1]: pi = pd.period_range(start='2000-01-01', freq='D', periods=10)

In [2]: s = pd.Series(np.arange(10), index=pi)

Expand All @@ -674,7 +674,7 @@ New Behavior:

.. ipython:: python

pi = pd.PeriodIndex(start='2000-01-01', freq='D', periods=10)
pi = pd.period_range(start='2000-01-01', freq='D', periods=10)

s = pd.Series(np.arange(10), index=pi)

Expand Down
3 changes: 2 additions & 1 deletion doc/source/whatsnew/v0.24.0.rst
Original file line number Diff line number Diff line change
Expand Up @@ -1148,7 +1148,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.api.types.is_period` is deprecated in favor of `pandas.api.types.is_period_dtype` (:issue:`23917`)
- :func:`pandas.api.types.is_datetimetz` is deprecated in favor of `pandas.api.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`)
- Creating a :class:`TimedeltaIndex`, :class:`DatetimeIndex`, or :class:`PeriodIndex` by passing range arguments `start`, `end`, and `periods` is deprecated in favor of :func:`timedelta_range`, :func:`date_range`, or :func:`period_range` (:issue:`23919`)
- Passing a string alias like ``'datetime64[ns, UTC]'`` as the ``unit`` parameter to :class:`DatetimeTZDtype` is deprecated. Use :class:`DatetimeTZDtype.construct_from_string` instead (:issue:`23990`).
- In :meth:`Series.where` with Categorical data, providing an ``other`` that is not present in the categories is deprecated. Convert the categorical to a different dtype or add the ``other`` to the categories first (:issue:`24077`).
- :meth:`Series.clip_lower`, :meth:`Series.clip_upper`, :meth:`DataFrame.clip_lower` and :meth:`DataFrame.clip_upper` are deprecated and will be removed in a future version. Use ``Series.clip(lower=threshold)``, ``Series.clip(upper=threshold)`` and the equivalent ``DataFrame`` methods (:issue:`24203`)
Expand Down Expand Up @@ -1310,6 +1310,7 @@ Datetimelike
- Bug in :meth:`Series.combine_first` not properly aligning categoricals, so that missing values in ``self`` where not filled by valid values from ``other`` (:issue:`24147`)
- Bug in :func:`DataFrame.combine` with datetimelike values raising a TypeError (:issue:`23079`)
- Bug in :func:`date_range` with frequency of ``Day`` or higher where dates sufficiently far in the future could wrap around to the past instead of raising ``OutOfBoundsDatetime`` (:issue:`14187`)
- Bug in :func:`period_range` ignoring the frequency of ``start`` and ``end`` when those are provided as :class:`Period` objects (:issue:`20535`).
- Bug in :class:`PeriodIndex` with attribute ``freq.n`` greater than 1 where adding a :class:`DateOffset` object would return incorrect results (:issue:`23215`)
- Bug in :class:`Series` that interpreted string indices as lists of characters when setting datetimelike values (:issue:`23451`)
- Bug in :class:`Timestamp` constructor which would drop the frequency of an input :class:`Timestamp` (:issue:`22311`)
Expand Down
29 changes: 23 additions & 6 deletions pandas/core/indexes/datetimes.py
Original file line number Diff line number Diff line change
Expand Up @@ -81,15 +81,27 @@ class DatetimeIndex(DatetimeArray, DatetimeIndexOpsMixin, Int64Index):
start : starting value, datetime-like, optional
If data is None, start is used as the start point in generating regular
timestamp data.

.. deprecated:: 0.24.0

periods : int, optional, > 0
Number of periods to generate, if generating index. Takes precedence
over end argument
end : end time, datetime-like, optional

.. deprecated:: 0.24.0

end : end time, datetime-like, optional
If periods is none, generated index will extend to first conforming
time on or just past end argument

.. deprecated:: 0.24.0

closed : string or None, default None
Make the interval closed with respect to the given frequency to
the 'left', 'right', or both sides (None)

.. deprecated:: 0.24. 0

tz : pytz.timezone or dateutil.tz.tzfile
ambiguous : 'infer', bool-ndarray, 'NaT', default 'raise'
When clocks moved backward due to DST, ambiguous times may arise.
Expand Down Expand Up @@ -166,12 +178,16 @@ class DatetimeIndex(DatetimeArray, DatetimeIndexOpsMixin, Int64Index):
To learn more about the frequency strings, please see `this link
<http://pandas.pydata.org/pandas-docs/stable/timeseries.html#offset-aliases>`__.

Creating a DatetimeIndex based on `start`, `periods`, and `end` has
been deprecated in favor of :func:`date_range`.

See Also
---------
Index : The base pandas Index type.
TimedeltaIndex : Index of timedelta64 data.
PeriodIndex : Index of Period data.
pandas.to_datetime : Convert argument to datetime.
to_datetime : Convert argument to datetime.
date_range : Create a fixed-frequency DatetimeIndex.
"""
_typ = 'datetimeindex'
_join_precedence = 10
Expand Down Expand Up @@ -223,14 +239,15 @@ def __new__(cls, data=None,
verify_integrity = True

if data is None:
warnings.warn("Creating a DatetimeIndex by passing range "
"endpoints is deprecated. Use "
"`pandas.date_range` instead.",
FutureWarning, stacklevel=2)
dtarr = DatetimeArray._generate_range(
start, end, periods,
freq=freq, tz=tz, normalize=normalize,
closed=closed, ambiguous=ambiguous)
warnings.warn("Creating a DatetimeIndex by passing range "
"endpoints is deprecated. Use "
"`pandas.date_range` instead.",
FutureWarning, stacklevel=2)

return cls(dtarr, name=name)

if is_scalar(data):
Expand Down
65 changes: 55 additions & 10 deletions pandas/core/indexes/period.py
Original file line number Diff line number Diff line change
Expand Up @@ -92,12 +92,21 @@ class PeriodIndex(DatelikeOps, DatetimeIndexOpsMixin, Int64Index,
start : starting value, period-like, optional
If data is None, used as the start point in generating regular
period data.

.. deprecated:: 0.24.0

periods : int, optional, > 0
Number of periods to generate, if generating index. Takes precedence
over end argument

.. deprecated:: 0.24.0

end : end value, period-like, optional
If periods is none, generated index will extend to first conforming
period on or just past end argument

.. deprecated:: 0.24.0

year : int, array, or Series, default None
month : int, array, or Series, default None
quarter : int, array, or Series, default None
Expand Down Expand Up @@ -138,18 +147,22 @@ class PeriodIndex(DatelikeOps, DatetimeIndexOpsMixin, Int64Index,
strftime
to_timestamp

Notes
-----
Creating a PeriodIndex based on `start`, `periods`, and `end` has
been deprecated in favor of :func:`period_range`.

Examples
--------
>>> idx = pd.PeriodIndex(year=year_arr, quarter=q_arr)

>>> idx2 = pd.PeriodIndex(start='2000', end='2010', freq='A')

See Also
---------
Index : The base pandas Index type.
Period : Represents a period of time.
DatetimeIndex : Index with datetime64 data.
TimedeltaIndex : Index of timedelta64 data.
period_range : Create a fixed-frequency PeriodIndex.
"""
_typ = 'periodindex'
_attributes = ['name', 'freq']
Expand Down Expand Up @@ -181,8 +194,32 @@ def __new__(cls, data=None, ordinal=None, freq=None, start=None, end=None,

if data is None and ordinal is None:
# range-based.
data, freq = PeriodArray._generate_range(start, end, periods,
freq, fields)
data, freq2 = PeriodArray._generate_range(start, end, periods,
freq, fields)
# PeriodArray._generate range does validate that fields is
# empty when really using the range-based constructor.
if not fields:
msg = ("Creating a PeriodIndex by passing range "
"endpoints is deprecated. Use "
"`pandas.period_range` instead.")
# period_range differs from PeriodIndex for cases like
# start="2000", periods=4
# PeriodIndex interprets that as A-DEC freq.
# period_range interprets it as 'D' freq.
cond = (
freq is None and (
(start and not isinstance(start, Period)) or
(end and not isinstance(end, Period))
)
)
if cond:
msg += (
" Note that the default `freq` may differ. Pass "
"'freq=\"{}\"' to ensure the same output."
).format(freq2.freqstr)
warnings.warn(msg, FutureWarning, stacklevel=2)
freq = freq2

data = PeriodArray(data, freq=freq)
else:
freq = validate_dtype_freq(dtype, freq)
Expand Down Expand Up @@ -939,7 +976,7 @@ def base(self):
PeriodIndex._add_datetimelike_methods()


def period_range(start=None, end=None, periods=None, freq='D', name=None):
def period_range(start=None, end=None, periods=None, freq=None, name=None):
"""
Return a fixed frequency PeriodIndex, with day (calendar) as the default
frequency
Expand All @@ -952,8 +989,11 @@ def period_range(start=None, end=None, periods=None, freq='D', name=None):
Right bound for generating periods
periods : integer, default None
Number of periods to generate
freq : string or DateOffset, default 'D'
Frequency alias
freq : string or DateOffset, optional
Frequency alias. By default the freq is taken from `start` or `end`
if those are Period objects. Otherwise, the default is ``"D"`` for
daily frequency.

name : string, default None
Name of the resulting PeriodIndex

Expand Down Expand Up @@ -990,6 +1030,11 @@ def period_range(start=None, end=None, periods=None, freq='D', name=None):
if com.count_not_none(start, end, periods) != 2:
raise ValueError('Of the three parameters: start, end, and periods, '
'exactly two must be specified')

return PeriodIndex(start=start, end=end, periods=periods,
freq=freq, name=name)
if freq is None and (not isinstance(start, Period)
and not isinstance(end, Period)):
freq = 'D'

data, freq = PeriodArray._generate_range(start, end, periods, freq,
fields={})
data = PeriodArray(data, freq=freq)
return PeriodIndex(data, name=name)
19 changes: 17 additions & 2 deletions pandas/core/indexes/timedeltas.py
Original file line number Diff line number Diff line change
Expand Up @@ -64,15 +64,27 @@ class TimedeltaIndex(TimedeltaArray, DatetimeIndexOpsMixin,
start : starting value, timedelta-like, optional
If data is None, start is used as the start point in generating regular
timedelta data.

.. deprecated:: 0.24.0

periods : int, optional, > 0
Number of periods to generate, if generating index. Takes precedence
over end argument
end : end time, timedelta-like, optional

.. deprecated:: 0.24.0

end : end time, timedelta-like, optional
If periods is none, generated index will extend to first conforming
time on or just past end argument

.. deprecated:: 0.24. 0

closed : string or None, default None
Make the interval closed with respect to the given frequency to
the 'left', 'right', or both sides (None)

.. deprecated:: 0.24. 0

name : object
Name to be stored in the index

Expand Down Expand Up @@ -100,12 +112,15 @@ class TimedeltaIndex(TimedeltaArray, DatetimeIndexOpsMixin,
Timedelta : Represents a duration between two dates or times.
DatetimeIndex : Index of datetime64 data.
PeriodIndex : Index of Period data.
timedelta_range : Create a fixed-frequency TimedeltaIndex.

Notes
-----

To learn more about the frequency strings, please see `this link
<http://pandas.pydata.org/pandas-docs/stable/timeseries.html#offset-aliases>`__.

Creating a TimedeltaIndex based on `start`, `periods`, and `end` has
been deprecated in favor of :func:`timedelta_range`.
"""

_typ = 'timedeltaindex'
Expand Down
12 changes: 6 additions & 6 deletions pandas/core/resample.py
Original file line number Diff line number Diff line change
Expand Up @@ -1491,10 +1491,10 @@ def _get_time_period_bins(self, ax):
binner = labels = PeriodIndex(data=[], freq=freq, name=ax.name)
return binner, [], labels

labels = binner = PeriodIndex(start=ax[0],
end=ax[-1],
freq=freq,
name=ax.name)
labels = binner = pd.period_range(start=ax[0],
end=ax[-1],
freq=freq,
name=ax.name)

end_stamps = (labels + freq).asfreq(freq, 's').to_timestamp()
if ax.tzinfo:
Expand Down Expand Up @@ -1543,8 +1543,8 @@ def _get_period_bins(self, ax):
bin_shift = start_offset.n % freq_mult
start = p_start

labels = binner = PeriodIndex(start=start, end=end,
freq=self.freq, name=ax.name)
labels = binner = pd.period_range(start=start, end=end,
freq=self.freq, name=ax.name)

i8 = memb.asi8

Expand Down
4 changes: 2 additions & 2 deletions pandas/plotting/_converter.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@
import pandas.core.common as com
from pandas.core.index import Index
from pandas.core.indexes.datetimes import date_range
from pandas.core.indexes.period import Period, PeriodIndex
from pandas.core.indexes.period import Period, PeriodIndex, period_range
import pandas.core.tools.datetimes as tools

import pandas.tseries.frequencies as frequencies
Expand Down Expand Up @@ -630,7 +630,7 @@ def _daily_finder(vmin, vmax, freq):
(vmin, vmax) = (Period(ordinal=int(vmin), freq=freq),
Period(ordinal=int(vmax), freq=freq))
span = vmax.ordinal - vmin.ordinal + 1
dates_ = PeriodIndex(start=vmin, end=vmax, freq=freq)
dates_ = period_range(start=vmin, end=vmax, freq=freq)
# Initialize the output
info = np.zeros(span,
dtype=[('val', np.int64), ('maj', bool),
Expand Down
4 changes: 2 additions & 2 deletions pandas/tests/frame/test_join.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
import pytest
import numpy as np

from pandas import DataFrame, Index, PeriodIndex
from pandas import DataFrame, Index, period_range
from pandas.tests.frame.common import TestData
import pandas.util.testing as tm

Expand All @@ -13,7 +13,7 @@ def frame_with_period_index():
return DataFrame(
data=np.arange(20).reshape(4, 5),
columns=list('abcde'),
index=PeriodIndex(start='2000', freq='A', periods=4))
index=period_range(start='2000', freq='A', periods=4))


@pytest.fixture
Expand Down
2 changes: 1 addition & 1 deletion pandas/tests/frame/test_period.py
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ def test_frame_setitem(self):

def test_frame_to_time_stamp(self):
K = 5
index = PeriodIndex(freq='A', start='1/1/2001', end='12/1/2009')
index = period_range(freq='A', start='1/1/2001', end='12/1/2009')
df = DataFrame(randn(len(index), K), index=index)
df['mix'] = 'a'

Expand Down
Loading