Skip to content

Commit 24e8fc0

Browse files
author
Chang She
committed
BUG: asof failure with PeriodIndex #1883
1 parent 815256a commit 24e8fc0

File tree

3 files changed

+67
-7
lines changed

3 files changed

+67
-7
lines changed

pandas/core/series.py

+20-4
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@
2121
_ensure_index, _handle_legacy_indexes)
2222
from pandas.core.indexing import _SeriesIndexer
2323
from pandas.tseries.index import DatetimeIndex
24-
from pandas.tseries.period import PeriodIndex
24+
from pandas.tseries.period import PeriodIndex, Period
2525
from pandas.util import py3compat
2626
from pandas.util.terminal import get_terminal_size
2727
import pandas.core.common as com
@@ -2537,11 +2537,18 @@ def asof(self, where):
25372537
where = datetools.to_datetime(where)
25382538

25392539
values = self.values
2540+
time_index = self.index
2541+
is_periodindex = isinstance(self.index, PeriodIndex)
2542+
if is_periodindex:
2543+
time_index = Index(self.index.values)
25402544

25412545
if not hasattr(where, '__iter__'):
2542-
if where < self.index[0]:
2546+
if is_periodindex:
2547+
where = Period(where, freq=self.index.freq).ordinal
2548+
2549+
if where < time_index[0]:
25432550
return np.nan
2544-
loc = self.index.searchsorted(where, side='right')
2551+
loc = time_index.searchsorted(where, side='right')
25452552
if loc > 0:
25462553
loc -= 1
25472554
while isnull(values[loc]) and loc > 0:
@@ -2551,7 +2558,16 @@ def asof(self, where):
25512558
if not isinstance(where, Index):
25522559
where = Index(where)
25532560

2554-
locs = self.index.asof_locs(where, notnull(values))
2561+
where_index = where
2562+
if is_periodindex:
2563+
if isinstance(where_index, DatetimeIndex):
2564+
where_index = PeriodIndex(where_index.values,
2565+
freq=self.index.freq)
2566+
2567+
if isinstance(where_index, PeriodIndex):
2568+
where_index = Index(where_index.values)
2569+
2570+
locs = time_index.asof_locs(where_index, notnull(values))
25552571
new_values = com.take_1d(values, locs)
25562572
return Series(new_values, index=where, name=self.name)
25572573

pandas/tests/test_series.py

+44
Original file line numberDiff line numberDiff line change
@@ -2276,6 +2276,50 @@ def test_asof(self):
22762276
d = self.ts.index[0] - datetools.bday
22772277
self.assert_(np.isnan(self.ts.asof(d)))
22782278

2279+
def test_asof_periodindex(self):
2280+
from pandas import period_range, PeriodIndex
2281+
# array or list or dates
2282+
N = 50
2283+
rng = period_range('1/1/1990', periods=N, freq='H')
2284+
ts = Series(np.random.randn(N), index=rng)
2285+
ts[15:30] = np.nan
2286+
dates = date_range('1/1/1990', periods=N * 3, freq='37min')
2287+
2288+
result = ts.asof(dates)
2289+
self.assert_(notnull(result).all())
2290+
lb = ts.index[14]
2291+
ub = ts.index[30]
2292+
2293+
result = ts.asof(list(dates))
2294+
self.assert_(notnull(result).all())
2295+
lb = ts.index[14]
2296+
ub = ts.index[30]
2297+
2298+
pix = PeriodIndex(result.index.values, freq='H')
2299+
mask = (pix >= lb) & (pix < ub)
2300+
rs = result[mask]
2301+
self.assert_((rs == ts[lb]).all())
2302+
2303+
ts[5:10] = np.NaN
2304+
ts[15:20] = np.NaN
2305+
2306+
val1 = ts.asof(ts.index[7])
2307+
val2 = ts.asof(ts.index[19])
2308+
2309+
self.assertEqual(val1, ts[4])
2310+
self.assertEqual(val2, ts[14])
2311+
2312+
# accepts strings
2313+
val1 = ts.asof(str(ts.index[7]))
2314+
self.assertEqual(val1, ts[4])
2315+
2316+
# in there
2317+
self.assertEqual(ts.asof(ts.index[3]), ts[3])
2318+
2319+
# no as of value
2320+
d = ts.index[0].to_timestamp() - datetools.bday
2321+
self.assert_(np.isnan(ts.asof(d)))
2322+
22792323
def test_asof_more(self):
22802324
from pandas import date_range
22812325
s = Series([nan, nan, 1, 2, nan, nan, 3, 4, 5],

pandas/tseries/period.py

+3-3
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,6 @@
11
# pylint: disable=E1101,E1103,W0232
2+
import operator
3+
24
from datetime import datetime, date
35
import numpy as np
46

@@ -33,6 +35,7 @@ def f(self):
3335
f.__name__ = name
3436
return property(f)
3537

38+
3639
class Period(object):
3740

3841
__slots__ = ['freq', 'ordinal']
@@ -423,8 +426,6 @@ def dt64arr_to_periodarr(data, freq):
423426
return plib.dt64arr_to_periodarr(data.view('i8'), base)
424427

425428
# --- Period index sketch
426-
427-
428429
def _period_index_cmp(opname):
429430
"""
430431
Wrap comparison operations to convert datetime-like to datetime64
@@ -445,7 +446,6 @@ def wrapper(self, other):
445446
return result
446447
return wrapper
447448

448-
449449
_INT64_DTYPE = np.dtype(np.int64)
450450
_NS_DTYPE = np.dtype('M8[ns]')
451451

0 commit comments

Comments
 (0)