From d289c901346964f8814c118e1ab9a178ff6bf62d Mon Sep 17 00:00:00 2001 From: jbrockmendel Date: Fri, 28 Feb 2020 19:31:14 -0800 Subject: [PATCH 1/2] REF: Remove BlockManager.rename_axis --- pandas/core/generic.py | 7 +++--- pandas/core/indexes/api.py | 21 +++++++++++++++++ pandas/core/internals/__init__.py | 2 -- pandas/core/internals/managers.py | 39 +------------------------------ pandas/core/reshape/merge.py | 5 ++-- 5 files changed, 28 insertions(+), 46 deletions(-) diff --git a/pandas/core/generic.py b/pandas/core/generic.py index 25770c2c6470c..b31dcf9ad1e04 100644 --- a/pandas/core/generic.py +++ b/pandas/core/generic.py @@ -94,6 +94,7 @@ MultiIndex, RangeIndex, ensure_index, + transform_index, ) from pandas.core.indexes.datetimes import DatetimeIndex from pandas.core.indexes.period import Period, PeriodIndex @@ -967,7 +968,6 @@ def rename( continue ax = self._get_axis(axis_no) - baxis = self._get_block_manager_axis(axis_no) f = com.get_rename_function(replacements) if level is not None: @@ -984,9 +984,8 @@ def rename( ] raise KeyError(f"{missing_labels} not found in axis") - result._data = result._data.rename_axis( - f, axis=baxis, copy=copy, level=level - ) + new_index = transform_index(ax, f, level) + result.set_axis(new_index, axis=axis_no, inplace=True) result._clear_item_cache() if inplace: diff --git a/pandas/core/indexes/api.py b/pandas/core/indexes/api.py index 0a23d38ace37e..0c70f7a1fa351 100644 --- a/pandas/core/indexes/api.py +++ b/pandas/core/indexes/api.py @@ -311,3 +311,24 @@ def all_indexes_same(indexes): if not first.equals(index): return False return True + + +def transform_index(index: Index, func, level=None) -> Index: + """ + Apply function to all values found in index. + + This includes transforming multiindex entries separately. + Only apply function to one level of the MultiIndex if level is specified. + """ + if isinstance(index, MultiIndex): + if level is not None: + items = [ + tuple(func(y) if i == level else y for i, y in enumerate(x)) + for x in index + ] + else: + items = [tuple(func(y) for y in x) for x in index] + return MultiIndex.from_tuples(items, names=index.names) + else: + items = [func(x) for x in index] + return Index(items, name=index.name, tupleize_cols=False) diff --git a/pandas/core/internals/__init__.py b/pandas/core/internals/__init__.py index 37a3405554745..e70652b81c42f 100644 --- a/pandas/core/internals/__init__.py +++ b/pandas/core/internals/__init__.py @@ -17,7 +17,6 @@ from pandas.core.internals.managers import ( BlockManager, SingleBlockManager, - _transform_index, concatenate_block_managers, create_block_manager_from_arrays, create_block_manager_from_blocks, @@ -40,7 +39,6 @@ "_block_shape", "BlockManager", "SingleBlockManager", - "_transform_index", "concatenate_block_managers", "create_block_manager_from_arrays", "create_block_manager_from_blocks", diff --git a/pandas/core/internals/managers.py b/pandas/core/internals/managers.py index e397167e4881f..fb148e498052a 100644 --- a/pandas/core/internals/managers.py +++ b/pandas/core/internals/managers.py @@ -34,7 +34,7 @@ import pandas.core.algorithms as algos from pandas.core.base import PandasObject from pandas.core.indexers import maybe_convert_indices -from pandas.core.indexes.api import Index, MultiIndex, ensure_index +from pandas.core.indexes.api import Index, ensure_index from pandas.core.internals.blocks import ( Block, CategoricalBlock, @@ -184,21 +184,6 @@ def set_axis(self, axis, new_labels): self.axes[axis] = new_labels - def rename_axis(self, mapper, axis, copy: bool = True, level=None): - """ - Rename one of axes. - - Parameters - ---------- - mapper : unary callable - axis : int - copy : bool, default True - level : int, default None - """ - obj = self.copy(deep=copy) - obj.set_axis(axis, _transform_index(self.axes[axis], mapper, level)) - return obj - @property def _is_single_block(self) -> bool: if self.ndim == 1: @@ -1897,28 +1882,6 @@ def _compare_or_regex_search(a, b, regex=False): return result -def _transform_index(index, func, level=None): - """ - Apply function to all values found in index. - - This includes transforming multiindex entries separately. - Only apply function to one level of the MultiIndex if level is specified. - - """ - if isinstance(index, MultiIndex): - if level is not None: - items = [ - tuple(func(y) if i == level else y for i, y in enumerate(x)) - for x in index - ] - else: - items = [tuple(func(y) for y in x) for x in index] - return MultiIndex.from_tuples(items, names=index.names) - else: - items = [func(x) for x in index] - return Index(items, name=index.name, tupleize_cols=False) - - def _fast_count_smallints(arr): """Faster version of set(arr) for sequences of small numbers.""" counts = np.bincount(arr.astype(np.int_)) diff --git a/pandas/core/reshape/merge.py b/pandas/core/reshape/merge.py index 49ac1b6cfa52b..bc6dcb94cc69b 100644 --- a/pandas/core/reshape/merge.py +++ b/pandas/core/reshape/merge.py @@ -46,7 +46,8 @@ from pandas.core.arrays.categorical import _recode_for_categories import pandas.core.common as com from pandas.core.frame import _merge_doc -from pandas.core.internals import _transform_index, concatenate_block_managers +from pandas.core.indexes.api import transform_index +from pandas.core.internals import concatenate_block_managers from pandas.core.sorting import is_int64_overflow_possible if TYPE_CHECKING: @@ -2028,4 +2029,4 @@ def renamer(x, suffix): lrenamer = partial(renamer, suffix=lsuffix) rrenamer = partial(renamer, suffix=rsuffix) - return (_transform_index(left, lrenamer), _transform_index(right, rrenamer)) + return (transform_index(left, lrenamer), transform_index(right, rrenamer)) From afce8bb788b06f6e3aa5550a4674e778c715e34a Mon Sep 17 00:00:00 2001 From: jbrockmendel Date: Sun, 8 Mar 2020 09:53:53 -0700 Subject: [PATCH 2/2] make transform_index method --- pandas/core/generic.py | 3 +-- pandas/core/indexes/api.py | 21 --------------------- pandas/core/indexes/base.py | 21 +++++++++++++++++++++ pandas/core/reshape/merge.py | 3 +-- 4 files changed, 23 insertions(+), 25 deletions(-) diff --git a/pandas/core/generic.py b/pandas/core/generic.py index e324b7ace7d7f..5a220f7de9895 100644 --- a/pandas/core/generic.py +++ b/pandas/core/generic.py @@ -93,7 +93,6 @@ MultiIndex, RangeIndex, ensure_index, - transform_index, ) from pandas.core.indexes.datetimes import DatetimeIndex from pandas.core.indexes.period import Period, PeriodIndex @@ -984,7 +983,7 @@ def rename( ] raise KeyError(f"{missing_labels} not found in axis") - new_index = transform_index(ax, f, level) + new_index = ax._transform_index(f, level) result.set_axis(new_index, axis=axis_no, inplace=True) result._clear_item_cache() diff --git a/pandas/core/indexes/api.py b/pandas/core/indexes/api.py index 0c70f7a1fa351..0a23d38ace37e 100644 --- a/pandas/core/indexes/api.py +++ b/pandas/core/indexes/api.py @@ -311,24 +311,3 @@ def all_indexes_same(indexes): if not first.equals(index): return False return True - - -def transform_index(index: Index, func, level=None) -> Index: - """ - Apply function to all values found in index. - - This includes transforming multiindex entries separately. - Only apply function to one level of the MultiIndex if level is specified. - """ - if isinstance(index, MultiIndex): - if level is not None: - items = [ - tuple(func(y) if i == level else y for i, y in enumerate(x)) - for x in index - ] - else: - items = [tuple(func(y) for y in x) for x in index] - return MultiIndex.from_tuples(items, names=index.names) - else: - items = [func(x) for x in index] - return Index(items, name=index.name, tupleize_cols=False) diff --git a/pandas/core/indexes/base.py b/pandas/core/indexes/base.py index 3eab757311ccb..5c06b1c17f0ab 100644 --- a/pandas/core/indexes/base.py +++ b/pandas/core/indexes/base.py @@ -4738,6 +4738,27 @@ def map(self, mapper, na_action=None): return Index(new_values, **attributes) + # TODO: De-duplicate with map, xref GH#32349 + def _transform_index(self, func, level=None) -> "Index": + """ + Apply function to all values found in index. + + This includes transforming multiindex entries separately. + Only apply function to one level of the MultiIndex if level is specified. + """ + if isinstance(self, ABCMultiIndex): + if level is not None: + items = [ + tuple(func(y) if i == level else y for i, y in enumerate(x)) + for x in self + ] + else: + items = [tuple(func(y) for y in x) for x in self] + return type(self).from_tuples(items, names=self.names) + else: + items = [func(x) for x in self] + return Index(items, name=self.name, tupleize_cols=False) + def isin(self, values, level=None): """ Return a boolean array where the index values are in `values`. diff --git a/pandas/core/reshape/merge.py b/pandas/core/reshape/merge.py index f83904fdbc9ea..daaa5138f7654 100644 --- a/pandas/core/reshape/merge.py +++ b/pandas/core/reshape/merge.py @@ -46,7 +46,6 @@ from pandas.core.arrays.categorical import _recode_for_categories import pandas.core.common as com from pandas.core.frame import _merge_doc -from pandas.core.indexes.api import transform_index from pandas.core.internals import concatenate_block_managers from pandas.core.sorting import is_int64_overflow_possible @@ -2023,4 +2022,4 @@ def renamer(x, suffix): lrenamer = partial(renamer, suffix=lsuffix) rrenamer = partial(renamer, suffix=rsuffix) - return (transform_index(left, lrenamer), transform_index(right, rrenamer)) + return (left._transform_index(lrenamer), right._transform_index(rrenamer))