Skip to content

Commit 2f0a094

Browse files
jbrockmendelSeeminSyed
authored andcommitted
BUG: PeriodIndex.asof_locs (pandas-dev#32310)
1 parent 5568354 commit 2f0a094

File tree

4 files changed

+59
-9
lines changed

4 files changed

+59
-9
lines changed

pandas/core/indexes/period.py

+7-8
Original file line numberDiff line numberDiff line change
@@ -370,27 +370,26 @@ def __array_wrap__(self, result, context=None):
370370
# cannot pass _simple_new as it is
371371
return type(self)(result, freq=self.freq, name=self.name)
372372

373-
def asof_locs(self, where, mask):
373+
def asof_locs(self, where, mask: np.ndarray) -> np.ndarray:
374374
"""
375375
where : array of timestamps
376376
mask : array of booleans where data is not NA
377-
378377
"""
379378
where_idx = where
380379
if isinstance(where_idx, DatetimeIndex):
381380
where_idx = PeriodIndex(where_idx.values, freq=self.freq)
381+
elif not isinstance(where_idx, PeriodIndex):
382+
raise TypeError("asof_locs `where` must be DatetimeIndex or PeriodIndex")
383+
elif where_idx.freq != self.freq:
384+
raise raise_on_incompatible(self, where_idx)
382385

383-
locs = self._ndarray_values[mask].searchsorted(
384-
where_idx._ndarray_values, side="right"
385-
)
386+
locs = self.asi8[mask].searchsorted(where_idx.asi8, side="right")
386387

387388
locs = np.where(locs > 0, locs - 1, 0)
388389
result = np.arange(len(self))[mask].take(locs)
389390

390391
first = mask.argmax()
391-
result[
392-
(locs == 0) & (where_idx._ndarray_values < self._ndarray_values[first])
393-
] = -1
392+
result[(locs == 0) & (where_idx.asi8 < self.asi8[first])] = -1
394393

395394
return result
396395

pandas/tests/frame/methods/test_asof.py

+21-1
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,17 @@
11
import numpy as np
22
import pytest
33

4-
from pandas import DataFrame, Period, Series, Timestamp, date_range, to_datetime
4+
from pandas._libs.tslibs import IncompatibleFrequency
5+
6+
from pandas import (
7+
DataFrame,
8+
Period,
9+
Series,
10+
Timestamp,
11+
date_range,
12+
period_range,
13+
to_datetime,
14+
)
515
import pandas._testing as tm
616

717

@@ -156,3 +166,13 @@ def test_is_copy(self, date_range_frame):
156166

157167
with tm.assert_produces_warning(None):
158168
result["C"] = 1
169+
170+
def test_asof_periodindex_mismatched_freq(self):
171+
N = 50
172+
rng = period_range("1/1/1990", periods=N, freq="H")
173+
df = DataFrame(np.random.randn(N), index=rng)
174+
175+
# Mismatched freq
176+
msg = "Input has different freq"
177+
with pytest.raises(IncompatibleFrequency, match=msg):
178+
df.asof(rng.asfreq("D"))

pandas/tests/indexes/period/test_indexing.py

+24
Original file line numberDiff line numberDiff line change
@@ -795,3 +795,27 @@ def test_period_index_indexer(self):
795795
tm.assert_frame_equal(df, df.loc[list(idx)])
796796
tm.assert_frame_equal(df.iloc[0:5], df.loc[idx[0:5]])
797797
tm.assert_frame_equal(df, df.loc[list(idx)])
798+
799+
800+
class TestAsOfLocs:
801+
def test_asof_locs_mismatched_type(self):
802+
dti = pd.date_range("2016-01-01", periods=3)
803+
pi = dti.to_period("D")
804+
pi2 = dti.to_period("H")
805+
806+
mask = np.array([0, 1, 0], dtype=bool)
807+
808+
msg = "must be DatetimeIndex or PeriodIndex"
809+
with pytest.raises(TypeError, match=msg):
810+
pi.asof_locs(pd.Int64Index(pi.asi8), mask)
811+
812+
with pytest.raises(TypeError, match=msg):
813+
pi.asof_locs(pd.Float64Index(pi.asi8), mask)
814+
815+
with pytest.raises(TypeError, match=msg):
816+
# TimedeltaIndex
817+
pi.asof_locs(dti - dti, mask)
818+
819+
msg = "Input has different freq=H"
820+
with pytest.raises(libperiod.IncompatibleFrequency, match=msg):
821+
pi.asof_locs(pi2, mask)

pandas/tests/series/methods/test_asof.py

+7
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
import numpy as np
22
import pytest
33

4+
from pandas._libs.tslibs import IncompatibleFrequency
5+
46
from pandas import Series, Timestamp, date_range, isna, notna, offsets
57
import pandas._testing as tm
68

@@ -132,6 +134,11 @@ def test_periodindex(self):
132134
d = ts.index[0].to_timestamp() - offsets.BDay()
133135
assert isna(ts.asof(d))
134136

137+
# Mismatched freq
138+
msg = "Input has different freq"
139+
with pytest.raises(IncompatibleFrequency, match=msg):
140+
ts.asof(rng.asfreq("D"))
141+
135142
def test_errors(self):
136143

137144
s = Series(

0 commit comments

Comments
 (0)