Skip to content

BUG: Cast a key to NaT before get loc from Index #13687

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

Closed
wants to merge 1 commit into from
Closed
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
2 changes: 2 additions & 0 deletions doc/source/whatsnew/v0.19.0.txt
Original file line number Diff line number Diff line change
Expand Up @@ -614,3 +614,5 @@ Bug Fixes
- Bug in ``groupby`` with ``as_index=False`` returns all NaN's when grouping on multiple columns including a categorical one (:issue:`13204`)

- Bug where ``pd.read_gbq()`` could throw ``ImportError: No module named discovery`` as a result of a naming conflict with another python package called apiclient (:issue:`13454`)

- Bug in Checking for any NaT-like objects in a `TimedeltaIndex` always returns ``True`` (:issue:`13603`)
6 changes: 5 additions & 1 deletion pandas/tseries/tdi.py
Original file line number Diff line number Diff line change
Expand Up @@ -697,6 +697,10 @@ def get_loc(self, key, method=None, tolerance=None):
-------
loc : int
"""

if isnull(key):
key = tslib.NaT

if tolerance is not None:
# try converting tolerance now, so errors don't get swallowed by
# the try/except clauses below
Expand Down Expand Up @@ -754,7 +758,7 @@ def _maybe_cast_slice_bound(self, label, side, kind):
def _get_string_slice(self, key, use_lhs=True, use_rhs=True):
freq = getattr(self, 'freqstr',
getattr(self, 'inferred_freq', None))
if is_integer(key) or is_float(key):
if is_integer(key) or is_float(key) or key is tslib.NaT:
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

iNaT is an integer already

Copy link
Contributor Author

@yui-knk yui-knk Jul 18, 2016

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We cast a key to NaT. And NaT is not an integer.

In [111]: pd.lib.is_integer(pd.tslib.iNaT)
Out[111]: 1

In [112]: pd.lib.is_integer(pd.tslib.NaT)
Out[112]: 0

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

see my other comment
use isnull and don't change internal cython code that should is not relevant

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

iNaT IS by definition an integer

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

further we don't use lib.is_integer ever directly
import from pandas.types.common (as it is)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for your reviews.

use isnull and don't change internal cython code that should is not relevant

I updated to use isnull and do not change on cython codes
https://github.com/pydata/pandas/pull/13687/files#diff-c03d3accabc2e2f441d87b961f4425d7R701

further we don't use lib.is_integer ever directly

I use lib.is_integer only ipython, this PR does not use lib.is_integer, sorry to confuse you.

iNaT IS by definition an integer

Sure. But this PR converts a key to NaT (not iNaT) which may not be integer, so we need to check key is tslib.NaT or not.

self._invalid_indexer('slice', key)
loc = self._partial_td_slice(key, freq, use_lhs=use_lhs,
use_rhs=use_rhs)
Expand Down
19 changes: 19 additions & 0 deletions pandas/tseries/tests/test_timedeltas.py
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,25 @@ class TestTimedeltas(tm.TestCase):
def setUp(self):
pass

def test_get_loc_nat(self):
tidx = TimedeltaIndex(['1 days 01:00:00', 'NaT', '2 days 01:00:00'])

self.assertEqual(tidx.get_loc(pd.NaT), 1)
self.assertEqual(tidx.get_loc(None), 1)
self.assertEqual(tidx.get_loc(float('nan')), 1)
self.assertEqual(tidx.get_loc(np.nan), 1)

def test_contains(self):
# Checking for any NaT-like objects
# GH 13603
td = to_timedelta(range(5), unit='d') + pd.offsets.Hour(1)
for v in [pd.NaT, None, float('nan'), np.nan]:
self.assertFalse((v in td))

td = to_timedelta([pd.NaT])
for v in [pd.NaT, None, float('nan'), np.nan]:
self.assertTrue((v in td))

def test_construction(self):
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I added!


expected = np.timedelta64(10, 'D').astype('m8[ns]').view('i8')
Expand Down