-
-
Notifications
You must be signed in to change notification settings - Fork 18.7k
Closed
Labels
Description
Pandas version checks
-
I have checked that this issue has not already been reported.
-
I have confirmed this bug exists on the latest version of pandas.
-
I have confirmed this bug exists on the main branch of pandas.
Reproducible Example
import pandas as pd
start = pd.Period("2020", freq="3D")
a = pd.period_range(start, periods=2, freq=start.freq)
assert a[1] == start + 1
# Fails
b = pd.period_range(start, periods=2)
assert b[1] == start + 1
Issue Description
The issue lies in _get_ordinal_range
:
pandas/pandas/core/arrays/period.py
Lines 1044 to 1089 in 37d4c31
def _get_ordinal_range(start, end, periods, freq, mult=1): | |
if com.count_not_none(start, end, periods) != 2: | |
raise ValueError( | |
"Of the three parameters: start, end, and periods, " | |
"exactly two must be specified" | |
) | |
if freq is not None: | |
freq = to_offset(freq) | |
mult = freq.n | |
if start is not None: | |
start = Period(start, freq) | |
if end is not None: | |
end = Period(end, freq) | |
is_start_per = isinstance(start, Period) | |
is_end_per = isinstance(end, Period) | |
if is_start_per and is_end_per and start.freq != end.freq: | |
raise ValueError("start and end must have same freq") | |
if start is NaT or end is NaT: | |
raise ValueError("start and end must not be NaT") | |
if freq is None: | |
if is_start_per: | |
freq = start.freq | |
elif is_end_per: | |
freq = end.freq | |
else: # pragma: no cover | |
raise ValueError("Could not infer freq from start/end") | |
if periods is not None: | |
periods = periods * mult | |
if start is None: | |
data = np.arange( | |
end.ordinal - periods + mult, end.ordinal + 1, mult, dtype=np.int64 | |
) | |
else: | |
data = np.arange( | |
start.ordinal, start.ordinal + periods, mult, dtype=np.int64 | |
) | |
else: | |
data = np.arange(start.ordinal, end.ordinal + 1, mult, dtype=np.int64) | |
return data, freq |
A fix could be to replace:
pandas/pandas/core/arrays/period.py
Lines 1068 to 1072 in 37d4c31
if freq is None: | |
if is_start_per: | |
freq = start.freq | |
elif is_end_per: | |
freq = end.freq |
with
if freq is None:
if is_start_per:
freq = start.freq
mult = freq.n
elif is_end_per:
freq = end.freq
mult = freq.n
Expected Behavior
Omitting the freq
argument of pd.period_range
should be the same as passing the freq
of the start or end field to it via freq=
.
Installed Versions
Not relevant to issue.
kashif and rsnirwan