Skip to content

Commit 5ed4705

Browse files
authored
BUG: PeriodIndex[B].to_timestamp inferring "D" instead of "B". (#44105)
1 parent 2cc339a commit 5ed4705

File tree

3 files changed

+37
-1
lines changed

3 files changed

+37
-1
lines changed

doc/source/whatsnew/v1.4.0.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -579,6 +579,7 @@ I/O
579579
Period
580580
^^^^^^
581581
- Bug in adding a :class:`Period` object to a ``np.timedelta64`` object incorrectly raising ``TypeError`` (:issue:`44182`)
582+
- Bug in :meth:`PeriodIndex.to_timestamp` when the index has ``freq="B"`` inferring ``freq="D"`` for its result instead of ``freq="B"`` (:issue:`44105`)
582583
-
583584

584585
Plotting

pandas/core/arrays/period.py

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212

1313
import numpy as np
1414

15+
from pandas._libs import algos as libalgos
1516
from pandas._libs.arrays import NDArrayBacked
1617
from pandas._libs.tslibs import (
1718
BaseOffset,
@@ -506,7 +507,22 @@ def to_timestamp(self, freq=None, how: str = "start") -> DatetimeArray:
506507
new_parr = self.asfreq(freq, how=how)
507508

508509
new_data = libperiod.periodarr_to_dt64arr(new_parr.asi8, base)
509-
return DatetimeArray(new_data)._with_freq("infer")
510+
dta = DatetimeArray(new_data)
511+
512+
if self.freq.name == "B":
513+
# See if we can retain BDay instead of Day in cases where
514+
# len(self) is too small for infer_freq to distinguish between them
515+
diffs = libalgos.unique_deltas(self.asi8)
516+
if len(diffs) == 1:
517+
diff = diffs[0]
518+
if diff == self.freq.n:
519+
dta._freq = self.freq
520+
elif diff == 1:
521+
dta._freq = self.freq.base
522+
# TODO: other cases?
523+
return dta
524+
else:
525+
return dta._with_freq("infer")
510526

511527
# --------------------------------------------------------------------
512528

pandas/tests/arrays/test_datetimelike.py

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1114,6 +1114,25 @@ def test_to_timestamp(self, how, arr1d):
11141114
# an EA-specific tm.assert_ function
11151115
tm.assert_index_equal(pd.Index(result), pd.Index(expected))
11161116

1117+
def test_to_timestamp_roundtrip_bday(self):
1118+
# Case where infer_freq inside would choose "D" instead of "B"
1119+
dta = pd.date_range("2021-10-18", periods=3, freq="B")._data
1120+
parr = dta.to_period()
1121+
result = parr.to_timestamp()
1122+
assert result.freq == "B"
1123+
tm.assert_extension_array_equal(result, dta)
1124+
1125+
dta2 = dta[::2]
1126+
parr2 = dta2.to_period()
1127+
result2 = parr2.to_timestamp()
1128+
assert result2.freq == "2B"
1129+
tm.assert_extension_array_equal(result2, dta2)
1130+
1131+
parr3 = dta.to_period("2B")
1132+
result3 = parr3.to_timestamp()
1133+
assert result3.freq == "B"
1134+
tm.assert_extension_array_equal(result3, dta)
1135+
11171136
def test_to_timestamp_out_of_bounds(self):
11181137
# GH#19643 previously overflowed silently
11191138
pi = pd.period_range("1500", freq="Y", periods=3)

0 commit comments

Comments
 (0)