Skip to content
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

API: Deprecate renamae_axis and reindex_axis #17842

Merged
merged 9 commits into from
Oct 11, 2017
7 changes: 5 additions & 2 deletions doc/source/basics.rst
Original file line number Diff line number Diff line change
Expand Up @@ -1201,8 +1201,11 @@ With a DataFrame, you can simultaneously reindex the index and columns:
df
df.reindex(index=['c', 'f', 'b'], columns=['three', 'two', 'one'])

For convenience, you may utilize the :meth:`~Series.reindex_axis` method, which
takes the labels and a keyword ``axis`` parameter.
You may also use ``reindex`` with an ``axis`` keyword:

.. ipython:: python

df.reindex(index=['c', 'f', 'b'], axis='index')

Note that the ``Index`` objects containing the actual axis labels can be
**shared** between objects. So if we have a Series and a DataFrame, the
Expand Down
2 changes: 2 additions & 0 deletions doc/source/whatsnew/v0.21.0.txt
Original file line number Diff line number Diff line change
Expand Up @@ -810,6 +810,8 @@ Deprecations
- ``.get_value`` and ``.set_value`` on ``Series``, ``DataFrame``, ``Panel``, ``SparseSeries``, and ``SparseDataFrame`` are deprecated in favor of using ``.iat[]`` or ``.at[]`` accessors (:issue:`15269`)
- Passing a non-existent column in ``.to_excel(..., columns=)`` is deprecated and will raise a ``KeyError`` in the future (:issue:`17295`)
- ``raise_on_error`` parameter to :func:`Series.where`, :func:`Series.mask`, :func:`DataFrame.where`, :func:`DataFrame.mask` is deprecated, in favor of ``errors=`` (:issue:`14968`)
- Using :meth:`DataFrame.rename_axis` and :meth:`Series.rename_axis` to alter index or column *labels* is now deprecated in favor of using ``.rename``. ``rename_axis`` may still be used to alter the name of the index or columns (:issue:`17833`).
- :meth:`~NDFrame.reindex_axis` has been deprecated in favor of :meth:`~NDFrame.reindex`. See :ref`here` <whatsnew_0210.enhancements.rename_reindex_axis> for more (:issue:`17833`).
Copy link
Member

Choose a reason for hiding this comment

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

'NDFrame' is not something that exists in the documentation. You can just use DataFrame (it will not be shown because of the ~, and the docstrings are the same for series/dataframe)


.. _whatsnew_0210.deprecations.select:

Expand Down
7 changes: 2 additions & 5 deletions pandas/core/computation/align.py
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,7 @@ def _align_core(terms):
for axis, items in zip(range(ndim), axes):
ti = terms[i].value

# TODO: handle this for when reindex_axis is removed...
if hasattr(ti, 'reindex_axis'):
Copy link
Member

Choose a reason for hiding this comment

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

and using 'reindex' instead of 'reindex_axis' is not good enough?

transpose = isinstance(ti, pd.Series) and naxes > 1
reindexer = axes[naxes - 1] if transpose else items
Expand All @@ -104,11 +105,7 @@ def _align_core(terms):
).format(axis=axis, term=terms[i].name, ordm=ordm)
warnings.warn(w, category=PerformanceWarning, stacklevel=6)

if transpose:
f = partial(ti.reindex, index=reindexer, copy=False)
else:
f = partial(ti.reindex_axis, reindexer, axis=axis,
copy=False)
f = partial(ti.reindex, reindexer, axis=axis, copy=False)

terms[i].update(f())

Expand Down
2 changes: 1 addition & 1 deletion pandas/core/frame.py
Original file line number Diff line number Diff line change
Expand Up @@ -2736,7 +2736,7 @@ def reindexer(value):
if isinstance(loc, (slice, Series, np.ndarray, Index)):
cols = maybe_droplevels(self.columns[loc], key)
if len(cols) and not cols.equals(value.columns):
value = value.reindex_axis(cols, axis=1)
value = value.reindex(cols, axis=1)
# now align rows
value = reindexer(value).T

Expand Down
44 changes: 27 additions & 17 deletions pandas/core/generic.py
Original file line number Diff line number Diff line change
Expand Up @@ -129,7 +129,7 @@ def __init__(self, data, axes=None, copy=False, dtype=None,

if axes is not None:
for i, ax in enumerate(axes):
data = data.reindex_axis(ax, axis=i)
data = data.reindex(ax, axis=i)

object.__setattr__(self, 'is_copy', None)
object.__setattr__(self, '_data', data)
Expand Down Expand Up @@ -893,17 +893,12 @@ def f(x):
rename.__doc__ = _shared_docs['rename']

def rename_axis(self, mapper, axis=0, copy=True, inplace=False):
"""
Alter index and / or columns using input function or functions.
A scalar or list-like for ``mapper`` will alter the ``Index.name``
or ``MultiIndex.names`` attribute.
A function or dict for ``mapper`` will alter the labels.
Function / dict values must be unique (1-to-1). Labels not contained in
a dict / Series will be left as-is.
"""Alter the name of the index or columns.

Parameters
----------
mapper : scalar, list-like, dict-like or function, optional
mapper : scalar, list-like, optional
Value to set the axis name attribute.
axis : int or string, default 0
copy : boolean, default True
Also copy underlying data
Expand All @@ -913,6 +908,13 @@ def rename_axis(self, mapper, axis=0, copy=True, inplace=False):
-------
renamed : type of caller or None if inplace=True

Notes
-----
Prior to version 0.21.0, ``rename_axis`` could also be used to change
the axis *labels* by passing a mapping or scalar. This behavior is
deprecated and will be removed in a future version. Use ``rename``
instead.

See Also
--------
pandas.NDFrame.rename
Copy link
Member

Choose a reason for hiding this comment

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

sidenote: this is useless (does not make a link). Unless you want to start with shared docstring/substitution, I would just explicitly add both for series/frame: pandas.Series.rename, pandas.DataFrame.rename

Expand All @@ -922,29 +924,29 @@ def rename_axis(self, mapper, axis=0, copy=True, inplace=False):
--------

>>> df = pd.DataFrame({"A": [1, 2, 3], "B": [4, 5, 6]})
>>> df.rename_axis("foo") # scalar, alters df.index.name
>>> df.rename_axis("foo")
A B
foo
0 1 4
1 2 5
2 3 6
>>> df.rename_axis(lambda x: 2 * x) # function: alters labels
A B
0 1 4
2 2 5
4 3 6
>>> df.rename_axis({"A": "ehh", "C": "see"}, axis="columns") # mapping
ehh B

>>> df.rename_axis("bar", axis="columns")
bar A B
0 1 4
1 2 5
2 3 6

"""
inplace = validate_bool_kwarg(inplace, 'inplace')
non_mapper = is_scalar(mapper) or (is_list_like(mapper) and not
is_dict_like(mapper))
if non_mapper:
return self._set_axis_name(mapper, axis=axis, inplace=inplace)
else:
msg = ("Using 'rename_axis' to alter labels is deprecated. "
"Use '.rename' instead")
warnings.warn(msg, FutureWarning, stacklevel=2)
axis = self._get_axis_name(axis)
d = {'copy': copy, 'inplace': inplace}
d[axis] = mapper
Expand Down Expand Up @@ -2981,6 +2983,11 @@ def reindex(self, *args, **kwargs):
tolerance = kwargs.pop('tolerance', None)
fill_value = kwargs.pop('fill_value', np.nan)

# Series.reindex doesn't use / need the axis kwarg
# We pop and ignore it here, to make writing Series/Frame generic code
# easier
kwargs.pop("axis", None)

if kwargs:
raise TypeError('reindex() got an unexpected keyword '
'argument "{0}"'.format(list(kwargs.keys())[0]))
Expand Down Expand Up @@ -3085,11 +3092,14 @@ def _reindex_multi(self, axes, copy, fill_value):
@Appender(_shared_docs['reindex_axis'] % _shared_doc_kwargs)
def reindex_axis(self, labels, axis=0, method=None, level=None, copy=True,
limit=None, fill_value=np.nan):
msg = ("'.reindex_axis' is deprecated and will be removed in a future "
"version. Use '.reindex' instead.")
self._consolidate_inplace()

axis_name = self._get_axis_name(axis)
axis_values = self._get_axis(axis_name)
method = missing.clean_reindex_fill_method(method)
warnings.warn(msg, FutureWarning, stacklevel=3)
new_index, indexer = axis_values.reindex(labels, method, level,
limit=limit)
return self._reindex_with_indexers({axis: [new_index, indexer]},
Expand Down
4 changes: 2 additions & 2 deletions pandas/core/groupby.py
Original file line number Diff line number Diff line change
Expand Up @@ -901,7 +901,7 @@ def reset_identity(values):
result.index.get_indexer_for(ax.values))
result = result.take(indexer, axis=self.axis)
else:
result = result.reindex_axis(ax, axis=self.axis)
result = result.reindex(ax, axis=self.axis)

elif self.group_keys:

Expand Down Expand Up @@ -4580,7 +4580,7 @@ def _get_sorted_data(self):

# this is sort of wasteful but...
sorted_axis = data.axes[self.axis].take(self.sort_idx)
sorted_data = data.reindex_axis(sorted_axis, axis=self.axis)
sorted_data = data.reindex(sorted_axis, axis=self.axis)

return sorted_data

Expand Down
4 changes: 2 additions & 2 deletions pandas/core/indexing.py
Original file line number Diff line number Diff line change
Expand Up @@ -368,7 +368,7 @@ def _setitem_with_indexer(self, indexer, value):
# so the object is the same
index = self.obj._get_axis(i)
labels = index.insert(len(index), key)
self.obj._data = self.obj.reindex_axis(labels, i)._data
self.obj._data = self.obj.reindex(labels, axis=i)._data
self.obj._maybe_update_cacher(clear=True)
self.obj.is_copy = None

Expand Down Expand Up @@ -1132,7 +1132,7 @@ def _getitem_iterable(self, key, axis=None):
if labels.is_unique and Index(keyarr).is_unique:

try:
return self.obj.reindex_axis(keyarr, axis=axis)
return self.obj.reindex(keyarr, axis=axis)
except AttributeError:

# Series
Expand Down
4 changes: 2 additions & 2 deletions pandas/core/internals.py
Original file line number Diff line number Diff line change
Expand Up @@ -3283,8 +3283,8 @@ def apply(self, f, axes=None, filter=None, do_integrity_check=False,

for k, obj in aligned_args.items():
axis = getattr(obj, '_info_axis_number', 0)
kwargs[k] = obj.reindex_axis(b_items, axis=axis,
copy=align_copy)
kwargs[k] = obj.reindex(b_items, axis=axis,
copy=align_copy)

kwargs['mgr'] = self
applied = getattr(b, f)(**kwargs)
Expand Down
2 changes: 1 addition & 1 deletion pandas/core/panel.py
Original file line number Diff line number Diff line change
Expand Up @@ -722,7 +722,7 @@ def dropna(self, axis=0, how='any', inplace=False):
cond = mask == per_slice

new_ax = self._get_axis(axis)[cond]
result = self.reindex_axis(new_ax, axis=axis)
result = self.reindex(new_ax, axis=axis)
if inplace:
self._update_inplace(result)
else:
Expand Down
4 changes: 2 additions & 2 deletions pandas/core/reshape/pivot.py
Original file line number Diff line number Diff line change
Expand Up @@ -101,14 +101,14 @@ def pivot_table(data, values=None, index=None, columns=None, aggfunc='mean',
try:
m = MultiIndex.from_arrays(cartesian_product(table.index.levels),
names=table.index.names)
table = table.reindex_axis(m, axis=0)
table = table.reindex(m, axis=0)
except AttributeError:
pass # it's a single level

try:
m = MultiIndex.from_arrays(cartesian_product(table.columns.levels),
names=table.columns.names)
table = table.reindex_axis(m, axis=1)
table = table.reindex(m, axis=1)
except AttributeError:
pass # it's a single level or a series

Expand Down
4 changes: 4 additions & 0 deletions pandas/core/series.py
Original file line number Diff line number Diff line change
Expand Up @@ -2615,6 +2615,10 @@ def reindex_axis(self, labels, axis=0, **kwargs):
""" for compatibility with higher dims """
if axis != 0:
raise ValueError("cannot reindex series on non-zero axis!")
msg = ("'.reindex_axis' is deprecated and will be removed in a future "
"version. Use '.reindex' instead.")
warnings.warn(msg, FutureWarning, stacklevel=2)

return self.reindex(index=labels, **kwargs)

def memory_usage(self, index=True, deep=False):
Expand Down
2 changes: 1 addition & 1 deletion pandas/core/sparse/scipy_sparse.py
Original file line number Diff line number Diff line change
Expand Up @@ -134,5 +134,5 @@ def _coo_to_sparse_series(A, dense_index=False):
i = range(A.shape[0])
j = range(A.shape[1])
ind = MultiIndex.from_product([i, j])
s = s.reindex_axis(ind)
s = s.reindex(ind)
return s
2 changes: 1 addition & 1 deletion pandas/io/pytables.py
Original file line number Diff line number Diff line change
Expand Up @@ -1040,7 +1040,7 @@ def append_to_multiple(self, d, value, selector, data_columns=None,
dc = data_columns if k == selector else None

# compute the val
val = value.reindex_axis(v, axis=axis)
val = value.reindex(v, axis=axis)

self.append(k, val, data_columns=dc, **kwargs)

Expand Down
2 changes: 1 addition & 1 deletion pandas/plotting/_core.py
Original file line number Diff line number Diff line change
Expand Up @@ -697,7 +697,7 @@ def _parse_errorbars(self, label, err):
from pandas import DataFrame, Series

def match_labels(data, e):
e = e.reindex_axis(data.index)
e = e.reindex(data.index)
return e

# key-matched DataFrame
Expand Down
19 changes: 19 additions & 0 deletions pandas/tests/frame/test_alter_axes.py
Original file line number Diff line number Diff line change
Expand Up @@ -436,6 +436,25 @@ def test_rename_axis_inplace(self):
assert no_return is None
assert_frame_equal(result, expected)

def test_rename_axis_warns(self):
# https://github.com/pandas-dev/pandas/issues/17833
df = pd.DataFrame({"A": [1, 2], "B": [1, 2]})
with tm.assert_produces_warning(FutureWarning) as w:
df.rename_axis(id, axis=0)
assert 'rename' in str(w[0].message)

with tm.assert_produces_warning(FutureWarning) as w:
df.rename_axis({0: 10, 1: 20}, axis=0)
assert 'rename' in str(w[0].message)

with tm.assert_produces_warning(FutureWarning) as w:
df.rename_axis(id, axis=1)
assert 'rename' in str(w[0].message)

with tm.assert_produces_warning(FutureWarning) as w:
df['A'].rename_axis(id)
assert 'rename' in str(w[0].message)

def test_rename_multiindex(self):

tuples_index = [('foo1', 'bar1'), ('foo2', 'bar2')]
Expand Down
18 changes: 13 additions & 5 deletions pandas/tests/frame/test_axis_select_reindex.py
Original file line number Diff line number Diff line change
Expand Up @@ -418,11 +418,13 @@ def test_reindex_fill_value(self):
assert_frame_equal(result, expected)

# reindex_axis
result = df.reindex_axis(lrange(15), fill_value=0., axis=0)
with tm.assert_produces_warning(FutureWarning):
result = df.reindex_axis(lrange(15), fill_value=0., axis=0)
expected = df.reindex(lrange(15)).fillna(0)
assert_frame_equal(result, expected)

result = df.reindex_axis(lrange(5), fill_value=0., axis=1)
with tm.assert_produces_warning(FutureWarning):
result = df.reindex_axis(lrange(5), fill_value=0., axis=1)
expected = df.reindex(columns=lrange(5)).fillna(0)
assert_frame_equal(result, expected)

Expand Down Expand Up @@ -1030,20 +1032,26 @@ def test_reindex_corner(self):

def test_reindex_axis(self):
cols = ['A', 'B', 'E']
reindexed1 = self.intframe.reindex_axis(cols, axis=1)
with tm.assert_produces_warning(FutureWarning) as m:
reindexed1 = self.intframe.reindex_axis(cols, axis=1)
assert 'reindex' in str(m[0].message)
reindexed2 = self.intframe.reindex(columns=cols)
assert_frame_equal(reindexed1, reindexed2)

rows = self.intframe.index[0:5]
reindexed1 = self.intframe.reindex_axis(rows, axis=0)
with tm.assert_produces_warning(FutureWarning) as m:
reindexed1 = self.intframe.reindex_axis(rows, axis=0)
assert 'reindex' in str(m[0].message)
reindexed2 = self.intframe.reindex(index=rows)
assert_frame_equal(reindexed1, reindexed2)

pytest.raises(ValueError, self.intframe.reindex_axis, rows, axis=2)

# no-op case
cols = self.frame.columns.copy()
newFrame = self.frame.reindex_axis(cols, axis=1)
with tm.assert_produces_warning(FutureWarning) as m:
newFrame = self.frame.reindex_axis(cols, axis=1)
assert 'reindex' in str(m[0].message)
assert_frame_equal(newFrame, self.frame)

def test_reindex_with_nans(self):
Expand Down
6 changes: 3 additions & 3 deletions pandas/tests/reshape/test_reshape.py
Original file line number Diff line number Diff line change
Expand Up @@ -311,7 +311,7 @@ def test_include_na(self):
'a': {0: 1, 1: 0, 2: 0},
'b': {0: 0, 1: 1, 2: 0}},
dtype=np.uint8)
exp_na = exp_na.reindex_axis(['a', 'b', nan], 1)
exp_na = exp_na.reindex(['a', 'b', nan], axis=1)
# hack (NaN handling in assert_index_equal)
exp_na.columns = res_na.columns
assert_frame_equal(res_na, exp_na)
Expand Down Expand Up @@ -542,8 +542,8 @@ def test_basic_drop_first_NA(self):
2: 0},
nan: {0: 0,
1: 0,
2: 1}}, dtype=np.uint8).reindex_axis(
['b', nan], 1)
2: 1}}, dtype=np.uint8).reindex(
['b', nan], axis=1)
assert_frame_equal(res_na, exp_na)

res_just_na = get_dummies([nan], dummy_na=True, sparse=self.sparse,
Expand Down
6 changes: 6 additions & 0 deletions pandas/tests/sparse/test_series.py
Original file line number Diff line number Diff line change
Expand Up @@ -1414,6 +1414,12 @@ def test_deprecated_numpy_func_call(self):
check_stacklevel=False):
getattr(getattr(self, series), func)()

def test_deprecated_reindex_axis(self):
# https://github.com/pandas-dev/pandas/issues/17833
with tm.assert_produces_warning(FutureWarning) as m:
self.bseries.reindex_axis([0, 1, 2])
assert 'reindex' in str(m[0].message)


@pytest.mark.parametrize(
'datetime_type', (np.datetime64,
Expand Down
2 changes: 1 addition & 1 deletion pandas/tests/test_multilevel.py
Original file line number Diff line number Diff line change
Expand Up @@ -1805,7 +1805,7 @@ def test_reindex_level_partial_selection(self):
expected = self.frame.iloc[[0, 1, 2, 7, 8, 9]]
tm.assert_frame_equal(result, expected)

result = self.frame.T.reindex_axis(['foo', 'qux'], axis=1, level=0)
result = self.frame.T.reindex(['foo', 'qux'], axis=1, level=0)
tm.assert_frame_equal(result, expected.T)

result = self.frame.loc[['foo', 'qux']]
Expand Down
Loading