From 7f7b1ae5d2d3a617633c3e8fdd53b5411aa707f5 Mon Sep 17 00:00:00 2001 From: Jeffrey Tratner Date: Thu, 12 Sep 2013 19:28:35 -0400 Subject: [PATCH 1/3] BUG: Fix copy s.t. it always copies index/columns. Only copies index/columns with `deep=True` on `BlockManager`. Plus some tests...yay! Change copy to make views of indices. Requires changing groupby to check whether indices are identical, rather than comparing with `is`. Plus add tests for name checks through everything. Also, fixes tests to use `is_()` rather than `is` CLN: Change groupby to use 'is_' instead --- doc/source/release.rst | 2 ++ pandas/core/groupby.py | 2 +- pandas/core/internals.py | 8 ++++++-- pandas/sparse/series.py | 8 ++++---- pandas/sparse/tests/test_sparse.py | 2 +- pandas/tests/test_frame.py | 24 ++++++++++++------------ pandas/tests/test_multilevel.py | 4 ++-- pandas/tests/test_panel.py | 7 +++++++ pandas/tests/test_panel4d.py | 5 ----- pandas/tests/test_series.py | 20 ++++++++++++-------- 10 files changed, 47 insertions(+), 35 deletions(-) diff --git a/doc/source/release.rst b/doc/source/release.rst index 04908ee8c9e03..285cea7938f91 100644 --- a/doc/source/release.rst +++ b/doc/source/release.rst @@ -455,6 +455,8 @@ Bug Fixes - Tests for fillna on empty Series (:issue:`4346`), thanks @immerrr - Fixed a bug where ``ValueError`` wasn't correctly raised when column names weren't strings (:issue:`4956`) + - Fixed ``copy()`` to shallow copy axes/indices as well and thereby keep + separate metadata. (:issue:`4202`, :issue:`4830`) pandas 0.12.0 ------------- diff --git a/pandas/core/groupby.py b/pandas/core/groupby.py index e5071bb4484a6..ce07981793f7b 100644 --- a/pandas/core/groupby.py +++ b/pandas/core/groupby.py @@ -1988,7 +1988,7 @@ def transform(self, func, *args, **kwargs): # broadcasting if isinstance(res, Series): - if res.index is obj.index: + if res.index.is_(obj.index): group.T.values[:] = res else: group.values[:] = res diff --git a/pandas/core/internals.py b/pandas/core/internals.py index 3ab1bfb2c58ed..8fcb64e6d0eda 100644 --- a/pandas/core/internals.py +++ b/pandas/core/internals.py @@ -2334,8 +2334,12 @@ def copy(self, deep=True): ------- copy : BlockManager """ - new_axes = list(self.axes) - return self.apply('copy', axes=new_axes, deep=deep, do_integrity_check=False) + if deep: + new_axes = [ax.view() for ax in self.axes] + else: + new_axes = list(self.axes) + return self.apply('copy', axes=new_axes, deep=deep, + ref_items=new_axes[0], do_integrity_check=False) def as_matrix(self, items=None): if len(self.blocks) == 0: diff --git a/pandas/sparse/series.py b/pandas/sparse/series.py index 5cb29d717235d..912393d01ef60 100644 --- a/pandas/sparse/series.py +++ b/pandas/sparse/series.py @@ -116,7 +116,7 @@ def __init__(self, data, index=None, sparse_index=None, kind='block', if is_sparse_array: if isinstance(data, SparseSeries) and index is None: - index = data.index + index = data.index.view() elif index is not None: assert(len(index) == len(data)) @@ -125,14 +125,14 @@ def __init__(self, data, index=None, sparse_index=None, kind='block', elif isinstance(data, SparseSeries): if index is None: - index = data.index + index = data.index.view() # extract the SingleBlockManager data = data._data elif isinstance(data, (Series, dict)): if index is None: - index = data.index + index = data.index.view() data = Series(data) data, sparse_index = make_sparse(data, kind=kind, @@ -150,7 +150,7 @@ def __init__(self, data, index=None, sparse_index=None, kind='block', if dtype is not None: data = data.astype(dtype) if index is None: - index = data.index + index = data.index.view() else: data = data.reindex(index, copy=False) diff --git a/pandas/sparse/tests/test_sparse.py b/pandas/sparse/tests/test_sparse.py index 45543547fd64b..a74872c8f193f 100644 --- a/pandas/sparse/tests/test_sparse.py +++ b/pandas/sparse/tests/test_sparse.py @@ -787,7 +787,7 @@ def test_copy(self): cp = self.frame.copy() tm.assert_isinstance(cp, SparseDataFrame) assert_sp_frame_equal(cp, self.frame) - self.assert_(cp.index is self.frame.index) + self.assert_(cp.index.is_(self.frame.index)) def test_constructor(self): for col, series in compat.iteritems(self.frame): diff --git a/pandas/tests/test_frame.py b/pandas/tests/test_frame.py index 0bc454d6ef2bc..7b753f5d6a367 100644 --- a/pandas/tests/test_frame.py +++ b/pandas/tests/test_frame.py @@ -1736,6 +1736,16 @@ class SafeForSparse(object): _multiprocess_can_split_ = True + def test_copy_index_name_checking(self): + # don't want to be able to modify the index stored elsewhere after + # making a copy + for attr in ('index', 'columns'): + ind = getattr(self.frame, attr) + ind.name = None + cp = self.frame.copy() + getattr(cp, attr).name = 'foo' + self.assert_(getattr(self.frame, attr).name is None) + def test_getitem_pop_assign_name(self): s = self.frame['A'] self.assertEqual(s.name, 'A') @@ -6040,16 +6050,6 @@ def test_copy(self): copy = self.mixed_frame.copy() self.assert_(copy._data is not self.mixed_frame._data) - # def test_copy_index_name_checking(self): - # # don't want to be able to modify the index stored elsewhere after - # # making a copy - - # self.frame.columns.name = None - # cp = self.frame.copy() - # cp.columns.name = 'foo' - - # self.assert_(self.frame.columns.name is None) - def _check_method(self, method='pearson', check_minp=False): if not check_minp: correls = self.frame.corr(method=method) @@ -7630,8 +7630,8 @@ def test_reindex(self): # corner cases - # Same index, copies values - newFrame = self.frame.reindex(self.frame.index) + # Same index, copies values but not index if copy=False + newFrame = self.frame.reindex(self.frame.index, copy=False) self.assert_(newFrame.index is self.frame.index) # length zero diff --git a/pandas/tests/test_multilevel.py b/pandas/tests/test_multilevel.py index d3d4368d8028e..2c8394bfde285 100644 --- a/pandas/tests/test_multilevel.py +++ b/pandas/tests/test_multilevel.py @@ -1195,11 +1195,11 @@ def test_count(self): result = frame.count(level='b') expect = self.frame.count(level=1) - assert_frame_equal(result, expect) + assert_frame_equal(result, expect, check_names=False) result = frame.count(level='a') expect = self.frame.count(level=0) - assert_frame_equal(result, expect) + assert_frame_equal(result, expect, check_names=False) series = self.series.copy() series.index.names = ['a', 'b'] diff --git a/pandas/tests/test_panel.py b/pandas/tests/test_panel.py index c78823779f6d0..a61212b341fa7 100644 --- a/pandas/tests/test_panel.py +++ b/pandas/tests/test_panel.py @@ -61,6 +61,13 @@ class SafeForLongAndSparse(object): def test_repr(self): foo = repr(self.panel) + def test_copy_names(self): + for attr in ('major_axis', 'minor_axis'): + getattr(self.panel, attr).name = None + cp = self.panel.copy() + getattr(cp, attr).name = 'foo' + self.assert_(getattr(self.panel, attr).name is None) + def test_iter(self): tm.equalContents(list(self.panel), self.panel.items) diff --git a/pandas/tests/test_panel4d.py b/pandas/tests/test_panel4d.py index 4f7e75b401216..1ce909b57402f 100644 --- a/pandas/tests/test_panel4d.py +++ b/pandas/tests/test_panel4d.py @@ -762,11 +762,6 @@ def test_reindex(self): major=self.panel4d.major_axis, minor=self.panel4d.minor_axis) - assert(result.labels is self.panel4d.labels) - assert(result.items is self.panel4d.items) - assert(result.major_axis is self.panel4d.major_axis) - assert(result.minor_axis is self.panel4d.minor_axis) - # don't necessarily copy result = self.panel4d.reindex() assert_panel4d_equal(result,self.panel4d) diff --git a/pandas/tests/test_series.py b/pandas/tests/test_series.py index 60dd42865818c..b2c5782d56b1f 100644 --- a/pandas/tests/test_series.py +++ b/pandas/tests/test_series.py @@ -64,14 +64,17 @@ def test_copy_name(self): result = self.ts.copy() self.assertEquals(result.name, self.ts.name) - # def test_copy_index_name_checking(self): - # don't want to be able to modify the index stored elsewhere after - # making a copy + def test_copy_index_name_checking(self): + # don't want to be able to modify the index stored elsewhere after + # making a copy - # self.ts.index.name = None - # cp = self.ts.copy() - # cp.index.name = 'foo' - # self.assert_(self.ts.index.name is None) + self.ts.index.name = None + self.assert_(self.ts.index.name is None) + self.assert_(self.ts is self.ts) + cp = self.ts.copy() + cp.index.name = 'foo' + print(self.ts.index.name) + self.assert_(self.ts.index.name is None) def test_append_preserve_name(self): result = self.ts[:5].append(self.ts[5:]) @@ -4270,7 +4273,8 @@ def test_align_sameindex(self): def test_reindex(self): identity = self.series.reindex(self.series.index) - self.assertEqual(id(self.series.index), id(identity.index)) + self.assert_(np.may_share_memory(self.series.index, identity.index)) + self.assert_(identity.index.is_(self.series.index)) subIndex = self.series.index[10:20] subSeries = self.series.reindex(subIndex) From 8de077895152666b6ec2225dd6a7b74216b2b578 Mon Sep 17 00:00:00 2001 From: jreback Date: Sat, 14 Sep 2013 21:16:05 -0400 Subject: [PATCH 2/3] ENH: enable deep copy for sparse Series/Panel --- pandas/sparse/panel.py | 20 +++++++++++++------- pandas/sparse/series.py | 2 +- 2 files changed, 14 insertions(+), 8 deletions(-) diff --git a/pandas/sparse/panel.py b/pandas/sparse/panel.py index 261443a95b111..ae981180022c7 100644 --- a/pandas/sparse/panel.py +++ b/pandas/sparse/panel.py @@ -235,19 +235,25 @@ def __setstate__(self, state): self._minor_axis = _ensure_index(com._unpickle_array(minor)) self._frames = frames - def copy(self): + def copy(self, deep=True): """ - Make a (shallow) copy of the sparse panel + Make a copy of the sparse panel Returns ------- copy : SparsePanel """ - return SparsePanel(self._frames.copy(), items=self.items, - major_axis=self.major_axis, - minor_axis=self.minor_axis, - default_fill_value=self.default_fill_value, - default_kind=self.default_kind) + + d = self._construct_axes_dict() + if deep: + new_data = dict((k, v.copy(deep=True)) for k, v in compat.iteritems(self._frames)) + d = dict((k, v.copy(deep=True)) for k, v in compat.iteritems(d)) + else: + new_data = self._frames.copy() + d['default_fill_value']=self.default_fill_value + d['default_kind']=self.default_kind + + return SparsePanel(new_data, **d) def to_frame(self, filter_observations=True): """ diff --git a/pandas/sparse/series.py b/pandas/sparse/series.py index 912393d01ef60..38003f0096df2 100644 --- a/pandas/sparse/series.py +++ b/pandas/sparse/series.py @@ -520,7 +520,7 @@ def copy(self, deep=True): if deep: new_data = self._data.copy() - return self._constructor(new_data, index=self.index, + return self._constructor(new_data, sparse_index=self.sp_index, fill_value=self.fill_value, name=self.name) From 42d1d743901753ffee5aab7bf4756aecc17a976c Mon Sep 17 00:00:00 2001 From: Jeffrey Tratner Date: Sun, 22 Sep 2013 19:06:33 -0400 Subject: [PATCH 3/3] CLN: PEP8 tests/test_index.py and core/index --- pandas/core/index.py | 76 +++++++++++++++++++++----------------- pandas/tests/test_index.py | 25 +++++++------ 2 files changed, 55 insertions(+), 46 deletions(-) diff --git a/pandas/core/index.py b/pandas/core/index.py index f2a22580f16b4..734a6ee15307d 100644 --- a/pandas/core/index.py +++ b/pandas/core/index.py @@ -16,7 +16,6 @@ import pandas.core.common as com from pandas.core.common import _values_from_object from pandas.core.config import get_option -import warnings __all__ = ['Index'] @@ -27,6 +26,7 @@ def _indexOp(opname): Wrapper function for index comparison operations, to avoid code duplication. """ + def wrapper(self, other): func = getattr(self.view(np.ndarray), opname) result = func(other) @@ -54,6 +54,7 @@ def _shouldbe_timestamp(obj): class Index(FrozenNDArray): + """ Immutable ndarray implementing an ordered, sliceable set. The basic object storing axis labels for all pandas objects @@ -160,7 +161,7 @@ def __new__(cls, data, dtype=None, copy=False, name=None, fastpath=False, elif np.isscalar(data): raise TypeError('Index(...) must be called with a collection ' - 'of some kind, %s was passed' % repr(data)) + 'of some kind, %s was passed' % repr(data)) else: # other iterable of some kind subarr = com._asarray_tuplesafe(data, dtype=object) @@ -171,7 +172,7 @@ def __new__(cls, data, dtype=None, copy=False, name=None, fastpath=False, return Int64Index(subarr.astype('i8'), copy=copy, name=name) elif inferred != 'string': if (inferred.startswith('datetime') or - tslib.is_timestamp_array(subarr)): + tslib.is_timestamp_array(subarr)): from pandas.tseries.index import DatetimeIndex return DatetimeIndex(data, copy=copy, name=name, **kwargs) elif inferred == 'period': @@ -234,7 +235,7 @@ def to_series(self): useful with map for returning an indexer based on an index """ import pandas as pd - return pd.Series(self.values,index=self,name=self.name) + return pd.Series(self.values, index=self, name=self.name) def astype(self, dtype): return Index(self.values.astype(dtype), name=self.name, @@ -279,7 +280,7 @@ def _get_names(self): def _set_names(self, values): if len(values) != 1: raise ValueError('Length of new names must be 1, got %d' - % len(values)) + % len(values)) self.name = values[0] names = property(fset=_set_names, fget=_get_names) @@ -335,11 +336,11 @@ def _has_complex_internals(self): def summary(self, name=None): if len(self) > 0: head = self[0] - if hasattr(head,'format') and\ + if hasattr(head, 'format') and\ not isinstance(head, compat.string_types): head = head.format() tail = self[-1] - if hasattr(tail,'format') and\ + if hasattr(tail, 'format') and\ not isinstance(tail, compat.string_types): tail = tail.format() index_summary = ', %s to %s' % (com.pprint_thing(head), @@ -571,7 +572,7 @@ def to_native_types(self, slicer=None, **kwargs): def _format_native_types(self, na_rep='', **kwargs): """ actually format my specific types """ mask = isnull(self) - values = np.array(self,dtype=object,copy=True) + values = np.array(self, dtype=object, copy=True) values[mask] = na_rep return values.tolist() @@ -595,7 +596,7 @@ def identical(self, other): Similar to equals, but check that other comparable attributes are also equal """ return self.equals(other) and all( - ( getattr(self,c,None) == getattr(other,c,None) for c in self._comparables )) + (getattr(self, c, None) == getattr(other, c, None) for c in self._comparables)) def asof(self, label): """ @@ -886,7 +887,8 @@ def set_value(self, arr, key, value): Fast lookup of value from 1-dimensional ndarray. Only use this if you know what you're doing """ - self._engine.set_value(_values_from_object(arr), _values_from_object(key), value) + self._engine.set_value( + _values_from_object(arr), _values_from_object(key), value) def get_level_values(self, level): """ @@ -1357,7 +1359,7 @@ def slice_locs(self, start=None, end=None): # get_loc will return a boolean array for non_uniques # if we are not monotonic - if isinstance(start_slice,np.ndarray): + if isinstance(start_slice, np.ndarray): raise KeyError("cannot peform a slice operation " "on a non-unique non-monotonic index") @@ -1379,7 +1381,7 @@ def slice_locs(self, start=None, end=None): if not is_unique: # get_loc will return a boolean array for non_uniques - if isinstance(end_slice,np.ndarray): + if isinstance(end_slice, np.ndarray): raise KeyError("cannot perform a slice operation " "on a non-unique non-monotonic index") @@ -1447,6 +1449,7 @@ def drop(self, labels): class Int64Index(Index): + """ Immutable ndarray implementing an ordered, sliceable set. The basic object storing axis labels for all pandas objects. Int64Index is a special case of `Index` @@ -1579,6 +1582,7 @@ def _wrap_joined_index(self, joined, other): class MultiIndex(Index): + """ Implements multi-level, a.k.a. hierarchical, index object for pandas objects @@ -1625,7 +1629,6 @@ def __new__(cls, levels=None, labels=None, sortorder=None, names=None, if names is not None: subarr._set_names(names) - if sortorder is not None: subarr.sortorder = int(sortorder) else: @@ -1636,7 +1639,6 @@ def __new__(cls, levels=None, labels=None, sortorder=None, names=None, def _get_levels(self): return self._levels - def _set_levels(self, levels, copy=False): # This is NOT part of the levels property because it should be # externally not allowed to set levels. User beware if you change @@ -1686,7 +1688,7 @@ def _get_labels(self): def _set_labels(self, labels, copy=False): if len(labels) != self.nlevels: raise ValueError("Length of levels and labels must be the same.") - self._labels = FrozenList(_ensure_frozen(labs,copy=copy)._shallow_copy() + self._labels = FrozenList(_ensure_frozen(labs, copy=copy)._shallow_copy() for labs in labels) def set_labels(self, labels, inplace=False): @@ -1811,13 +1813,13 @@ def _set_names(self, values): values = list(values) if len(values) != self.nlevels: raise ValueError('Length of names (%d) must be same as level ' - '(%d)' % (len(values),self.nlevels)) + '(%d)' % (len(values), self.nlevels)) # set the name for name, level in zip(values, self.levels): level.rename(name, inplace=True) - - names = property(fset=_set_names, fget=_get_names, doc="Names of levels in MultiIndex") + names = property( + fset=_set_names, fget=_get_names, doc="Names of levels in MultiIndex") def _format_native_types(self, **kwargs): return self.tolist() @@ -1845,7 +1847,7 @@ def _get_level_number(self, level): count = self.names.count(level) if count > 1: raise ValueError('The name %s occurs multiple times, use a ' - 'level number' % level) + 'level number' % level) level = self.names.index(level) except ValueError: if not isinstance(level, int): @@ -1980,9 +1982,9 @@ def format(self, space=2, sparsify=None, adjoin=True, names=False, formatted = lev.take(lab).format(formatter=formatter) # we have some NA - mask = lab==-1 + mask = lab == -1 if mask.any(): - formatted = np.array(formatted,dtype=object) + formatted = np.array(formatted, dtype=object) formatted[mask] = na_rep formatted = formatted.tolist() @@ -2000,7 +2002,6 @@ def format(self, space=2, sparsify=None, adjoin=True, names=False, level.append(com.pprint_thing(name, escape_chars=('\t', '\r', '\n')) if name is not None else '') - level.extend(np.array(lev, dtype=object)) result_levels.append(level) @@ -2010,8 +2011,9 @@ def format(self, space=2, sparsify=None, adjoin=True, names=False, if sparsify: sentinal = '' # GH3547 - # use value of sparsify as sentinal, unless it's an obvious "Truthey" value - if sparsify not in [True,1]: + # use value of sparsify as sentinal, unless it's an obvious + # "Truthey" value + if sparsify not in [True, 1]: sentinal = sparsify # little bit of a kludge job for #1217 result_levels = _sparsify(result_levels, @@ -2138,7 +2140,8 @@ def __contains__(self, key): def __reduce__(self): """Necessary for making this object picklable""" object_state = list(np.ndarray.__reduce__(self)) - subclass_state = (list(self.levels), list(self.labels), self.sortorder, list(self.names)) + subclass_state = (list(self.levels), list( + self.labels), self.sortorder, list(self.names)) object_state[2] = (object_state[2], subclass_state) return tuple(object_state) @@ -2490,7 +2493,8 @@ def reindex(self, target, method=None, level=None, limit=None, "with a method or limit") return self[target], target - raise Exception("cannot handle a non-takeable non-unique multi-index!") + raise Exception( + "cannot handle a non-takeable non-unique multi-index!") if not isinstance(target, MultiIndex): if indexer is None: @@ -2685,12 +2689,13 @@ def partial_selection(key): # here we have a completely specified key, but are using some partial string matching here # GH4758 - can_index_exactly = any([ l.is_all_dates and not isinstance(k,compat.string_types) for k, l in zip(key, self.levels) ]) - if any([ l.is_all_dates for k, l in zip(key, self.levels) ]) and not can_index_exactly: + can_index_exactly = any( + [l.is_all_dates and not isinstance(k, compat.string_types) for k, l in zip(key, self.levels)]) + if any([l.is_all_dates for k, l in zip(key, self.levels)]) and not can_index_exactly: indexer = slice(*self.slice_locs(key, key)) # we have a multiple selection here - if not indexer.stop-indexer.start == 1: + if not indexer.stop - indexer.start == 1: return partial_selection(key) key = tuple(self[indexer].tolist()[0]) @@ -2913,7 +2918,8 @@ def _assert_can_do_setop(self, other): def astype(self, dtype): if np.dtype(dtype) != np.object_: - raise TypeError("Setting %s dtype to anything other than object is not supported" % self.__class__) + raise TypeError( + "Setting %s dtype to anything other than object is not supported" % self.__class__) return self._shallow_copy() def insert(self, loc, item): @@ -2935,7 +2941,8 @@ def insert(self, loc, item): if not isinstance(item, tuple): item = (item,) + ('',) * (self.nlevels - 1) elif len(item) != self.nlevels: - raise ValueError('Item must have length equal to number of levels.') + raise ValueError( + 'Item must have length equal to number of levels.') new_levels = [] new_labels = [] @@ -2990,7 +2997,7 @@ def _wrap_joined_index(self, joined, other): # For utility purposes -def _sparsify(label_list, start=0,sentinal=''): +def _sparsify(label_list, start=0, sentinal=''): pivoted = lzip(*label_list) k = len(label_list) @@ -3031,7 +3038,7 @@ def _ensure_index(index_like, copy=False): if isinstance(index_like, list): if type(index_like) != list: index_like = list(index_like) - # #2200 ? + # 2200 ? converted, all_arrays = lib.clean_index_list(index_like) if len(converted) > 0 and all_arrays: @@ -3169,7 +3176,8 @@ def _get_consensus_names(indexes): # find the non-none names, need to tupleify to make # the set hashable, then reverse on return - consensus_names = set([ tuple(i.names) for i in indexes if all(n is not None for n in i.names) ]) + consensus_names = set([tuple(i.names) + for i in indexes if all(n is not None for n in i.names)]) if len(consensus_names) == 1: return list(list(consensus_names)[0]) return [None] * indexes[0].nlevels diff --git a/pandas/tests/test_index.py b/pandas/tests/test_index.py index 3e7ec5c3a3c12..e3c9da3630975 100644 --- a/pandas/tests/test_index.py +++ b/pandas/tests/test_index.py @@ -202,7 +202,8 @@ def test_is_(self): self.assertFalse(ind.is_(ind[:])) self.assertFalse(ind.is_(ind.view(np.ndarray).view(Index))) self.assertFalse(ind.is_(np.array(range(10)))) - self.assertTrue(ind.is_(ind.view().base)) # quasi-implementation dependent + # quasi-implementation dependent + self.assertTrue(ind.is_(ind.view().base)) ind2 = ind.view() ind2.name = 'bob' self.assertTrue(ind.is_(ind2)) @@ -441,7 +442,7 @@ def test_is_all_dates(self): def test_summary(self): self._check_method_works(Index.summary) # GH3869 - ind = Index(['{other}%s',"~:{range}:0"], name='A') + ind = Index(['{other}%s', "~:{range}:0"], name='A') result = ind.summary() # shouldn't be formatted accidentally. self.assert_('~:{range}:0' in result) @@ -1182,8 +1183,8 @@ def test_astype(self): assert_copy(actual.labels, expected.labels) self.check_level_names(actual, expected.names) - assertRaisesRegexp(TypeError, "^Setting.*dtype.*object", self.index.astype, np.dtype(int)) - + with assertRaisesRegexp(TypeError, "^Setting.*dtype.*object"): + self.index.astype(np.dtype(int)) def test_constructor_single_level(self): single_level = MultiIndex(levels=[['foo', 'bar', 'baz', 'qux']], @@ -1230,7 +1231,6 @@ def test_copy(self): self.assert_multiindex_copied(i_copy, self.index) - def test_shallow_copy(self): i_copy = self.index._shallow_copy() @@ -1497,10 +1497,11 @@ def test_slice_locs_with_type_mismatch(self): df = tm.makeCustomDataframe(5, 5) stacked = df.stack() idx = stacked.index - assertRaisesRegexp(TypeError, '^Level type mismatch', idx.slice_locs, timedelta(seconds=30)) + with assertRaisesRegexp(TypeError, '^Level type mismatch'): + idx.slice_locs(timedelta(seconds=30)) # TODO: Try creating a UnicodeDecodeError in exception message - assertRaisesRegexp(TypeError, '^Level type mismatch', idx.slice_locs, - df.index[1], (16, "a")) + with assertRaisesRegexp(TypeError, '^Level type mismatch'): + idx.slice_locs(df.index[1], (16, "a")) def test_slice_locs_not_sorted(self): index = MultiIndex(levels=[Index(lrange(4)), @@ -1672,7 +1673,7 @@ def test_format_sparse_config(self): warnings.filterwarnings('ignore', category=FutureWarning, module=".*format") - # #1538 + # GH1538 pd.set_option('display.multi_sparse', False) result = self.index.format() @@ -1734,11 +1735,11 @@ def test_identical(self): mi2 = self.index.copy() self.assert_(mi.identical(mi2)) - mi = mi.set_names(['new1','new2']) + mi = mi.set_names(['new1', 'new2']) self.assert_(mi.equals(mi2)) self.assert_(not mi.identical(mi2)) - mi2 = mi2.set_names(['new1','new2']) + mi2 = mi2.set_names(['new1', 'new2']) self.assert_(mi.identical(mi2)) def test_is_(self): @@ -1877,7 +1878,7 @@ def test_diff(self): expected.names = first.names self.assertEqual(first.names, result.names) assertRaisesRegexp(TypeError, "other must be a MultiIndex or a list" - " of tuples", first.diff, [1,2,3,4,5]) + " of tuples", first.diff, [1, 2, 3, 4, 5]) def test_from_tuples(self): assertRaisesRegexp(TypeError, 'Cannot infer number of levels from'