Skip to content

Commit c3e583c

Browse files
committed
More plumbing and fixing
* took care of wrappers in datetimes and interval * fix tolerance handling in extended dtype index construction * fix unpickling of old pickles and a bug in numeric index unpickling * fix tolerance for constructor delegation in `__new__`.
1 parent 623038e commit c3e583c

File tree

6 files changed

+34
-18
lines changed

6 files changed

+34
-18
lines changed

pandas/core/indexes/base.py

+14-5
Original file line numberDiff line numberDiff line change
@@ -293,7 +293,7 @@ def __new__(cls, data=None, dtype=None, copy=False, name=None,
293293
# coerce to the object dtype
294294
data = data.astype(object)
295295
return Index(data, dtype=object, copy=copy, name=name,
296-
**kwargs)
296+
tolerance=tolerance, **kwargs)
297297

298298
# index-like
299299
elif isinstance(data, (np.ndarray, Index, ABCSeries)):
@@ -306,7 +306,8 @@ def __new__(cls, data=None, dtype=None, copy=False, name=None,
306306
dtype=dtype, tolerance=tolerance,
307307
**kwargs)
308308
if dtype is not None and is_dtype_equal(_o_dtype, dtype):
309-
return Index(result.to_pydatetime(), dtype=_o_dtype)
309+
return Index(result.to_pydatetime(), dtype=_o_dtype,
310+
tolerance=tolerance)
310311
else:
311312
return result
312313

@@ -316,7 +317,8 @@ def __new__(cls, data=None, dtype=None, copy=False, name=None,
316317
result = TimedeltaIndex(data, copy=copy, name=name,
317318
tolerance=tolerance, **kwargs)
318319
if dtype is not None and _o_dtype == dtype:
319-
return Index(result.to_pytimedelta(), dtype=_o_dtype)
320+
return Index(result.to_pytimedelta(), dtype=_o_dtype,
321+
tolerance=tolerance)
320322
else:
321323
return result
322324

@@ -468,7 +470,8 @@ def __new__(cls, data=None, dtype=None, copy=False, name=None,
468470
# 10697
469471
from .multi import MultiIndex
470472
return MultiIndex.from_tuples(
471-
data, names=name or kwargs.get('names'))
473+
data, names=name or kwargs.get('names'),
474+
tolerance=tolerance)
472475
# other iterable of some kind
473476
subarr = com.asarray_tuplesafe(data, dtype=object)
474477
return Index(subarr, dtype=dtype, copy=copy, name=name,
@@ -1925,6 +1928,7 @@ def __setstate__(self, state):
19251928

19261929
if isinstance(state, dict):
19271930
self._data = state.pop('data')
1931+
self.tolerance = state.pop('tolerance', None)
19281932
for k, v in compat.iteritems(state):
19291933
setattr(self, k, v)
19301934

@@ -1940,6 +1944,7 @@ def __setstate__(self, state):
19401944
data = np.empty(state)
19411945
np.ndarray.__setstate__(data, state)
19421946

1947+
self.tolerance = None
19431948
self._data = data
19441949
self._reset_identity()
19451950
else:
@@ -2430,6 +2435,10 @@ def identical(self, other):
24302435
"""Similar to equals, but check that other comparable attributes are
24312436
also equal
24322437
"""
2438+
# FIXME: Should two indexes with different tolerances but are
2439+
# otherwise identical be considered identical?
2440+
# FIXME: Should this equality check take into account tolerances,
2441+
# or should it be forced to be strict (tolerance=0)?
24332442
return (self.equals(other) and
24342443
all((getattr(self, c, None) == getattr(other, c, None)
24352444
for c in self._comparables)) and
@@ -4563,7 +4572,7 @@ def unique(self, level=None):
45634572
if level is not None:
45644573
self._validate_index_level(level)
45654574
result = super(Index, self).unique()
4566-
return self._shallow_copy(result)
4575+
return self._shallow_copy(result, tolerance=self.tolerance)
45674576

45684577
def drop_duplicates(self, keep='first'):
45694578
"""

pandas/core/indexes/datetimes.py

+2-2
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,7 @@ def f(self):
6464
result = fget(self)
6565
if is_bool_dtype(result):
6666
return result
67-
return Index(result, name=self.name)
67+
return Index(result, name=self.name, tolerance=self.tolerance)
6868

6969
f.__name__ = name
7070
f.__doc__ = fget.__doc__
@@ -76,7 +76,7 @@ def _wrap_in_index(name):
7676

7777
def func(self, *args, **kwargs):
7878
result = meth(self, *args, **kwargs)
79-
return Index(result, name=self.name)
79+
return Index(result, name=self.name, tolerance=self.tolerance)
8080

8181
func.__doc__ = meth.__doc__
8282
func.__name__ = name

pandas/core/indexes/interval.py

+6-3
Original file line numberDiff line numberDiff line change
@@ -988,7 +988,7 @@ def equals(self, other, tolerance=None):
988988
self.closed == other.closed)
989989

990990
def _setop(op_name):
991-
def func(self, other):
991+
def func(self, other, tolerance=None):
992992
other = self._as_like_interval_index(other)
993993

994994
# GH 19016: ensure set op will not return a prohibited dtype
@@ -999,8 +999,10 @@ def func(self, other):
999999
'objects that have compatible dtypes')
10001000
raise TypeError(msg.format(op=op_name))
10011001

1002-
result = getattr(self._multiindex, op_name)(other._multiindex)
1002+
result = getattr(self._multiindex, op_name)(other._multiindex,
1003+
tolerance=tolerance)
10031004
result_name = self.name if self.name == other.name else None
1005+
result_tolerance = result.tolerance
10041006

10051007
# GH 19101: ensure empty results have correct dtype
10061008
if result.empty:
@@ -1009,7 +1011,8 @@ def func(self, other):
10091011
result = result.values
10101012

10111013
return type(self).from_tuples(result, closed=self.closed,
1012-
name=result_name)
1014+
name=result_name,
1015+
tolerance=result_tolerance)
10131016
return func
10141017

10151018
union = _setop('union')

pandas/core/indexes/multi.py

+2-1
Original file line numberDiff line numberDiff line change
@@ -1569,12 +1569,13 @@ def __setstate__(self, state):
15691569

15701570
nd_state, own_state = state
15711571
levels, labels, sortorder, names = own_state
1572+
tolerance = None
15721573

15731574
self._set_levels([Index(x) for x in levels], validate=False)
15741575
self._set_labels(labels)
15751576
self._set_names(names)
15761577
self.sortorder = sortorder
1577-
self.tolerance = None
1578+
self.tolerance = tolerance
15781579
self._verify_integrity()
15791580
self._reset_identity()
15801581

pandas/core/indexes/period.py

+1
Original file line numberDiff line numberDiff line change
@@ -811,6 +811,7 @@ def __setstate__(self, state):
811811
np.ndarray.__setstate__(self, state)
812812

813813
self._data = data
814+
self.tolerance = None
814815

815816
else:
816817
raise Exception("invalid pickle state")

pandas/core/indexes/range.py

+9-7
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@
1717

1818
import pandas.core.common as com
1919
from pandas.core import ops
20-
from pandas.core.indexes.base import Index, _index_shared_docs
20+
from pandas.core.indexes.base import Index, _index_shared_docs, ensure_index
2121
from pandas.util._decorators import Appender, cache_readonly
2222
import pandas.core.dtypes.concat as _concat
2323
import pandas.core.indexes.base as ibase
@@ -80,7 +80,8 @@ def __new__(cls, start=None, stop=None, step=None,
8080
if name is None:
8181
name = start.name
8282
return cls._simple_new(name=name,
83-
**dict(start._get_data_as_items()))
83+
**dict(start._get_data_as_items(),
84+
tolerance=tolerance))
8485

8586
# validate the arguments
8687
def ensure_int(value, field):
@@ -174,7 +175,8 @@ def _data(self):
174175

175176
@cache_readonly
176177
def _int64index(self):
177-
return Int64Index(self._data, name=self.name, fastpath=True)
178+
return Int64Index(self._data, name=self.name, fastpath=True,
179+
tolerance=self.tolerance)
178180

179181
def _get_data_as_items(self):
180182
""" return a list of tuples of start, stop, step """
@@ -321,6 +323,7 @@ def equals(self, other, tolerance=None):
321323
if isinstance(other, RangeIndex):
322324
ls = len(self)
323325
lo = len(other)
326+
# FIXME: intolerant
324327
return (ls == lo == 0 or
325328
ls == lo == 1 and
326329
self._start == other._start or
@@ -428,13 +431,12 @@ def union(self, other, tolerance=None):
428431
union : Index
429432
"""
430433
self._assert_can_do_setop(other)
434+
other = ensure_index(other)
431435
tolerance = self._choose_tolerance([other], tolerance=tolerance)
432436
if len(other) == 0 or self.equals(other, tolerance=tolerance):
433-
# FIXME: intolerant
434-
return self
437+
return self._shallow_copy(tolerance=tolerance)
435438
if len(self) == 0:
436-
# FIXME: intolerant
437-
return other
439+
return other._shallow_copy(tolerance=tolerance)
438440
if isinstance(other, RangeIndex):
439441
# FIXME: intolerant (how should I implement this?)
440442
start_s, step_s = self._start, self._step

0 commit comments

Comments
 (0)