Skip to content

Commit 4f049e6

Browse files
Brian TuBrian Tu
Brian Tu
authored and
Brian Tu
committed
clean up convert_tolerance to use np.asarray
1 parent a151f0f commit 4f049e6

File tree

7 files changed

+31
-111
lines changed

7 files changed

+31
-111
lines changed

pandas/core/indexes/base.py

Lines changed: 2 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -2601,8 +2601,7 @@ def get_indexer(self, target, method=None, limit=None, tolerance=None):
26012601
target = _ensure_index(target)
26022602
if tolerance is not None:
26032603
tolerance = self._convert_tolerance(tolerance)
2604-
if isinstance(tolerance, np.ndarray) and \
2605-
target.size != len(tolerance) and len(tolerance) > 1:
2604+
if target.size != tolerance.size and tolerance.size > 1:
26062605
raise ValueError('list-like tolerance size must match '
26072606
'target index size')
26082607

@@ -2639,7 +2638,7 @@ def get_indexer(self, target, method=None, limit=None, tolerance=None):
26392638

26402639
def _convert_tolerance(self, tolerance):
26412640
# override this method on subclasses
2642-
return _list_to_ndarray(tolerance)
2641+
return np.asarray(tolerance)
26432642

26442643
def _get_fill_indexer(self, target, method, limit=None, tolerance=None):
26452644
if self.is_monotonic_increasing and target.is_monotonic_increasing:
@@ -4029,17 +4028,6 @@ def invalid_op(self, other=None):
40294028
Index._add_comparison_methods()
40304029

40314030

4032-
def _list_to_ndarray(a):
4033-
"""Convert list-like to np.ndarray, otherwise leave as-is.
4034-
Used for converting tolerance to ndarray in _convert_tolerance.
4035-
"""
4036-
if isinstance(a, ABCSeries):
4037-
return a.values
4038-
elif isinstance(a, (list, tuple)):
4039-
return np.array(a)
4040-
return a
4041-
4042-
40434031
def _ensure_index_from_sequences(sequences, names=None):
40444032
"""Construct an index from sequences of data.
40454033

pandas/core/indexes/datetimelike.py

Lines changed: 5 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77

88
from pandas import compat
99
from pandas.compat.numpy import function as nv
10+
from pandas.core.tools.timedeltas import to_timedelta
1011

1112
import numpy as np
1213
from pandas.core.dtypes.common import (
@@ -27,8 +28,7 @@
2728
Timedelta, Timestamp, iNaT, NaT)
2829
from pandas._libs.period import Period
2930

30-
from pandas.core.indexes.base import (Index, _index_shared_docs,
31-
_list_to_ndarray)
31+
from pandas.core.indexes.base import Index, _index_shared_docs
3232
from pandas.util._decorators import Appender, cache_readonly
3333
import pandas.core.dtypes.concat as _concat
3434
import pandas.tseries.frequencies as frequencies
@@ -433,36 +433,9 @@ def asobject(self):
433433
return Index(self._box_values(self.asi8), name=self.name, dtype=object)
434434

435435
def _convert_tolerance(self, tolerance):
436-
tolerance = _list_to_ndarray(tolerance)
437-
if isinstance(tolerance, np.ndarray):
438-
if np.issubdtype(tolerance.dtype, np.timedelta64):
439-
return tolerance
440-
else:
441-
try:
442-
tolerance = np.array([np.timedelta64(x)
443-
for x in tolerance])
444-
# in case user mixes something like seconds and Month
445-
if not np.issubdtype(tolerance.dtype, np.timedelta64):
446-
raise TypeError('All values in tolerance array must '
447-
'be convertible to [ns]')
448-
except ValueError:
449-
raise TypeError(('tolerance argument for %s must contain '
450-
'objects convertible to np.timedelta64 '
451-
'if it is list type') %
452-
(type(self).__name__,))
453-
else:
454-
warnings.warn('Converting tolerance array to '
455-
'np.timedelta64 objects, consider doing '
456-
'preconverting for speed')
457-
return tolerance
458-
else:
459-
try:
460-
return Timedelta(tolerance).to_timedelta64()
461-
except ValueError:
462-
raise ValueError(('tolerance argument for %s must be '
463-
'convertible to Timedelta if it is a '
464-
'scalar: %r') %
465-
(type(self).__name__, tolerance))
436+
if not is_list_like(tolerance):
437+
tolerance = [tolerance]
438+
return np.asarray(to_timedelta(tolerance))
466439

467440
def _maybe_mask_results(self, result, fill_value=None, convert=None):
468441
"""

pandas/core/indexes/numeric.py

Lines changed: 10 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@
1515
from pandas import compat
1616
from pandas.core import algorithms
1717
from pandas.core.indexes.base import (
18-
Index, InvalidIndexError, _index_shared_docs, _list_to_ndarray)
18+
Index, InvalidIndexError, _index_shared_docs)
1919
from pandas.util._decorators import Appender, cache_readonly
2020
import pandas.core.indexes.base as ibase
2121

@@ -72,21 +72,17 @@ def _convert_for_op(self, value):
7272
return value
7373

7474
def _convert_tolerance(self, tolerance):
75-
tolerance = _list_to_ndarray(tolerance)
76-
if isinstance(tolerance, np.ndarray):
77-
if np.issubdtype(tolerance.dtype, np.number):
78-
return tolerance
79-
else:
75+
tolerance = np.asarray(tolerance)
76+
if not np.issubdtype(tolerance.dtype, np.number):
77+
if tolerance.ndim > 0:
8078
raise ValueError(('tolerance argument for %s must contain '
81-
'numeric elements if it is list type') %
82-
(type(self).__name__,))
83-
else:
84-
try:
85-
return float(tolerance)
86-
except ValueError:
79+
'numeric elements if it is list type') %
80+
(type(self).__name__,))
81+
else:
8782
raise ValueError(('tolerance argument for %s must be numeric '
88-
'if it is a scalar: %r') %
89-
(type(self).__name__, tolerance))
83+
'if it is a scalar: %r') %
84+
(type(self).__name__, tolerance))
85+
return tolerance
9086

9187
@classmethod
9288
def _assert_safe_casting(cls, data, subarr):

pandas/core/indexes/period.py

Lines changed: 2 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -639,10 +639,7 @@ def _maybe_convert_timedelta(self, other):
639639
if isinstance(offset, offsets.Tick):
640640
nanos = tslib._delta_to_nanoseconds(other)
641641
offset_nanos = tslib._delta_to_nanoseconds(offset)
642-
if isinstance(other, np.ndarray):
643-
check = np.all(nanos % offset_nanos == 0)
644-
else:
645-
check = nanos % offset_nanos == 0
642+
check = np.all(nanos % offset_nanos == 0)
646643
if check:
647644
return nanos // offset_nanos
648645
elif isinstance(other, offsets.DateOffset):
@@ -780,8 +777,7 @@ def get_indexer(self, target, method=None, limit=None, tolerance=None):
780777

781778
if tolerance is not None:
782779
tolerance = self._convert_tolerance(tolerance)
783-
if isinstance(tolerance, np.ndarray) and \
784-
target.size != tolerance.size and tolerance.size > 1:
780+
if target.size != tolerance.size and tolerance.size > 1:
785781
raise ValueError('list-like tolerance size must match '
786782
'target index size')
787783
return Index.get_indexer(self._int64index, target, method,
@@ -911,10 +907,6 @@ def _get_string_slice(self, key):
911907

912908
def _convert_tolerance(self, tolerance):
913909
tolerance = DatetimeIndexOpsMixin._convert_tolerance(self, tolerance)
914-
if isinstance(tolerance, np.ndarray) \
915-
and not np.issubdtype(tolerance.dtype, np.timedelta64):
916-
raise TypeError('All values in tolerance array must be '
917-
'convertible to [ns]')
918910
return self._maybe_convert_timedelta(tolerance)
919911

920912
def insert(self, loc, item):

pandas/tests/indexes/datetimes/test_datetime.py

Lines changed: 4 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,8 @@ def test_get_loc(self):
4141
tolerance=np.timedelta64(1, 'D')) == 1
4242
assert idx.get_loc('2000-01-01T12', method='nearest',
4343
tolerance=timedelta(1)) == 1
44-
with tm.assert_raises_regex(ValueError, 'must be convertible'):
44+
with tm.assert_raises_regex(ValueError,
45+
'unit abbreviation w/o a number'):
4546
idx.get_loc('2000-01-01T12', method='nearest', tolerance='foo')
4647
with pytest.raises(KeyError):
4748
idx.get_loc('2000-01-01T03', method='nearest', tolerance='2 hours')
@@ -102,28 +103,15 @@ def test_get_indexer(self):
102103
tol_raw = [pd.Timedelta('1 hour'),
103104
pd.Timedelta('1 hour'),
104105
pd.Timedelta('1 hour').to_timedelta64(), ]
105-
with pytest.warns(UserWarning) as speedwarning:
106-
tm.assert_numpy_array_equal(
107-
idx.get_indexer(target, 'nearest',
108-
tolerance=tol_raw),
109-
np.array([0, -1, 1], dtype=np.intp))
110-
assert len(speedwarning) == 1
111-
assert speedwarning[0].message.args[0]\
112-
.endswith('preconverting for speed')
113106
tm.assert_numpy_array_equal(
114107
idx.get_indexer(target, 'nearest',
115108
tolerance=[np.timedelta64(x) for x in tol_raw]),
116109
np.array([0, -1, 1], dtype=np.intp))
117-
with pytest.raises(
118-
TypeError,
119-
match='must contain objects convertible to np.timedelta64'):
120-
idx.get_indexer(target, 'nearest', tolerance=[1, 2, 3])
121110
tol_bad = [pd.Timedelta('2 hour').to_timedelta64(),
122111
pd.Timedelta('1 hour').to_timedelta64(),
123-
np.timedelta64(1, 'M'), ]
112+
'foo', ]
124113
with pytest.raises(
125-
TypeError, match='All values.* convertible to \\[ns\\]'),\
126-
pytest.warns(UserWarning):
114+
ValueError, match='abbreviation w/o a number'):
127115
idx.get_indexer(target, 'nearest', tolerance=tol_bad)
128116
with pytest.raises(ValueError):
129117
idx.get_indexer(idx[[0]], method='nearest', tolerance='foo')

pandas/tests/indexes/period/test_period.py

Lines changed: 5 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
from pandas import (PeriodIndex, period_range, notna, DatetimeIndex, NaT,
1010
Index, Period, Int64Index, Series, DataFrame, date_range,
1111
offsets, compat)
12+
from pandas.core.indexes.period import IncompatibleFrequency
1213

1314
from ..datetimelike import DatetimeLike
1415

@@ -81,7 +82,8 @@ def test_get_loc(self):
8182
tolerance=np.timedelta64(1, 'D')) == 1
8283
assert idx.get_loc('2000-01-02T12', method='nearest',
8384
tolerance=timedelta(1)) == 1
84-
with tm.assert_raises_regex(ValueError, 'must be convertible'):
85+
with tm.assert_raises_regex(ValueError,
86+
'unit abbreviation w/o a number'):
8587
idx.get_loc('2000-01-10', method='nearest', tolerance='foo')
8688

8789
msg = 'Input has different freq from PeriodIndex\\(freq=D\\)'
@@ -165,14 +167,6 @@ def test_get_indexer(self):
165167
tol_raw = [pd.Timedelta('1 hour'),
166168
pd.Timedelta('1 hour'),
167169
np.timedelta64(1, 'D'), ]
168-
with pytest.warns(UserWarning) as speedwarning:
169-
tm.assert_numpy_array_equal(
170-
idx.get_indexer(target, 'nearest',
171-
tolerance=tol_raw),
172-
np.array([0, -1, 1], dtype=np.intp))
173-
assert len(speedwarning) == 1
174-
assert speedwarning[0].message.args[0]\
175-
.endswith('preconverting for speed')
176170
tm.assert_numpy_array_equal(
177171
idx.get_indexer(target, 'nearest',
178172
tolerance=[np.timedelta64(x) for x in tol_raw]),
@@ -181,14 +175,9 @@ def test_get_indexer(self):
181175
pd.Timedelta('1 hour').to_timedelta64(),
182176
np.timedelta64(1, 'M'), ]
183177
with pytest.raises(
184-
TypeError,
185-
match='All values.* convertible to \\[ns\\]'),\
186-
pytest.warns(UserWarning):
178+
IncompatibleFrequency,
179+
match='Input has different freq from'):
187180
idx.get_indexer(target, 'nearest', tolerance=tol_bad)
188-
with pytest.raises(
189-
TypeError,
190-
match='must contain objects convertible to np.timedelta64'):
191-
idx.get_indexer(target, 'nearest', tolerance=[1, 2, 3])
192181

193182
def test_repeat(self):
194183
# GH10183

pandas/tests/indexes/timedeltas/test_timedelta.py

Lines changed: 3 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -60,12 +60,13 @@ def test_get_loc(self):
6060
assert idx.get_loc(idx[1], 'pad',
6161
tolerance=timedelta(0)) == 1
6262

63-
with tm.assert_raises_regex(ValueError, 'must be convertible'):
63+
with tm.assert_raises_regex(ValueError,
64+
'unit abbreviation w/o a number'):
6465
idx.get_loc(idx[1], method='nearest', tolerance='foo')
6566

6667
with pytest.raises(
6768
ValueError,
68-
match='tolerance size must match target index size'):
69+
match='tolerance size must match'):
6970
idx.get_loc(idx[1], method='nearest',
7071
tolerance=[Timedelta(0).to_timedelta64(),
7172
Timedelta(0).to_timedelta64()])
@@ -104,13 +105,6 @@ def test_get_indexer(self):
104105
tolerance=pd.Timedelta('1 hour'))
105106
tm.assert_numpy_array_equal(res, np.array([0, -1, 1], dtype=np.intp))
106107

107-
with pytest.warns(UserWarning):
108-
res = idx.get_indexer(target, 'nearest',
109-
tolerance=[pd.Timedelta('2 hour'),
110-
pd.Timedelta('5 hours'),
111-
pd.Timedelta('1 hour')])
112-
tm.assert_numpy_array_equal(res, np.array([0, -1, 1], dtype=np.intp))
113-
114108
def test_numeric_compat(self):
115109

116110
idx = self._holder(np.arange(5, dtype='int64'))

0 commit comments

Comments
 (0)