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

ENH: Add axis parameter to add_prefix and add_suffix #48085

Merged
merged 30 commits into from
Aug 31, 2022
Merged
Show file tree
Hide file tree
Changes from 16 commits
Commits
Show all changes
30 commits
Select commit Hold shift + click to select a range
4de8d75
Add axis parameter to add_prefix and add_suffix
dannyi96 Aug 15, 2022
d7ca739
Add axis parameter to add_prefix and add_suffix
dannyi96 Aug 15, 2022
e5a0310
Added testcases
dannyi96 Aug 15, 2022
802346a
docstring update
dannyi96 Aug 15, 2022
74eb3d8
docstring update
dannyi96 Aug 15, 2022
d83b0ea
updated whatsnew file
dannyi96 Aug 19, 2022
9ed51da
Merge branch 'main' into suffix_prefix_axis
dannyi96 Aug 19, 2022
db2095a
updated whatsnew file
dannyi96 Aug 19, 2022
c710605
updated whatsnew file
dannyi96 Aug 19, 2022
7752521
Merge branch 'main' into suffix_prefix_axis
dannyi96 Aug 20, 2022
6f1c967
Merge branch 'main' into suffix_prefix_axis
dannyi96 Aug 20, 2022
f61c373
Merge branch 'main' into suffix_prefix_axis
dannyi96 Aug 20, 2022
eb218b4
review comments
dannyi96 Aug 20, 2022
60c99cb
Merge branch 'main' into suffix_prefix_axis
dannyi96 Aug 20, 2022
56f9b25
Merge branch 'main' into suffix_prefix_axis
dannyi96 Aug 22, 2022
231567a
Merge branch 'main' into suffix_prefix_axis
dannyi96 Aug 23, 2022
afaab36
address merge conflixts
dannyi96 Aug 23, 2022
420b837
address merge conflixts
dannyi96 Aug 23, 2022
c5d17b9
Merge branch 'main' into suffix_prefix_axis
dannyi96 Aug 23, 2022
6ef3dc3
Merge branch 'main' into suffix_prefix_axis
dannyi96 Aug 24, 2022
4ac6741
Merge branch 'main' into suffix_prefix_axis
dannyi96 Aug 24, 2022
d760d11
Merge branch 'main' into suffix_prefix_axis
dannyi96 Aug 25, 2022
10a1ea2
updated whatsnew
dannyi96 Aug 26, 2022
a599a7a
Merge branch 'main' into suffix_prefix_axis
dannyi96 Aug 26, 2022
e024425
review comments
dannyi96 Aug 26, 2022
2a8e391
review comments
dannyi96 Aug 26, 2022
c51e20f
Merge branch 'main' into suffix_prefix_axis
dannyi96 Aug 28, 2022
888520a
Merge branch 'main' into suffix_prefix_axis
dannyi96 Aug 29, 2022
aac319d
Merge branch 'pandas-dev:main' into suffix_prefix_axis
dannyi96 Aug 30, 2022
a97b1f0
review comments
dannyi96 Aug 30, 2022
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions doc/source/whatsnew/v1.5.0.rst
Original file line number Diff line number Diff line change
Expand Up @@ -333,6 +333,7 @@ Other enhancements
- Added ``copy`` keyword to :meth:`Series.set_axis` and :meth:`DataFrame.set_axis` to allow user to set axis on a new object without necessarily copying the underlying data (:issue:`47932`)
- :meth:`DataFrame.set_index` now supports a ``copy`` keyword. If ``False``, the underlying data is not copied when a new :class:`DataFrame` is returned (:issue:`48043`)
- The method :meth:`.ExtensionArray.factorize` accepts ``use_na_sentinel=False`` for determining how null values are to be treated (:issue:`46601`)
- :meth:`Series.add_suffix`, :meth:`DataFrame.add_suffix`, :meth:`Series.add_prefix` and :meth:`DataFrame.add_prefix` support an ``axis`` argument. If ``axis`` is set, the default behaviour of which axis to consider can be overwritten (:issue:`47819`)

.. ---------------------------------------------------------------------------
.. _whatsnew_150.notable_bug_fixes:
Expand Down
32 changes: 28 additions & 4 deletions pandas/core/generic.py
Original file line number Diff line number Diff line change
Expand Up @@ -4619,7 +4619,9 @@ def _update_inplace(self, result, verify_is_copy: bool_t = True) -> None:
self._maybe_update_cacher(verify_is_copy=verify_is_copy, inplace=True)

@final
def add_prefix(self: NDFrameT, prefix: str) -> NDFrameT:
dannyi96 marked this conversation as resolved.
Show resolved Hide resolved
def add_prefix(
self: NDFrameT, prefix: str, copy: bool_t = True, axis: Axis | None = None
) -> NDFrameT:
"""
Prefix labels with string `prefix`.

Expand All @@ -4630,6 +4632,12 @@ def add_prefix(self: NDFrameT, prefix: str) -> NDFrameT:
----------
prefix : str
The string to add before each label.
copy : bool, default True
Whether to copy the underlying data.
axis : {{0 or 'index', 1 or 'columns', None}}, default None
Axis to add prefix on

.. versionadded:: 1.5.0

Returns
-------
Expand Down Expand Up @@ -4675,15 +4683,21 @@ def add_prefix(self: NDFrameT, prefix: str) -> NDFrameT:
"""
f = functools.partial("{prefix}{}".format, prefix=prefix)

mapper = {self._info_axis_name: f}
axis_name = self._info_axis_name
if axis is not None:
axis_name = self._get_axis_name(axis)

mapper = {axis_name: f}
# error: Incompatible return value type (got "Optional[NDFrameT]",
# expected "NDFrameT")
# error: Argument 1 to "rename" of "NDFrame" has incompatible type
# "**Dict[str, partial[str]]"; expected "Union[str, int, None]"
return self._rename(**mapper) # type: ignore[return-value, arg-type]

@final
def add_suffix(self: NDFrameT, suffix: str) -> NDFrameT:
def add_suffix(
self: NDFrameT, suffix: str, copy: bool_t = True, axis: Axis | None = None
) -> NDFrameT:
"""
Suffix labels with string `suffix`.

Expand All @@ -4694,6 +4708,12 @@ def add_suffix(self: NDFrameT, suffix: str) -> NDFrameT:
----------
suffix : str
The string to add after each label.
copy : bool, default True
Whether to copy the underlying data.
axis : {{0 or 'index', 1 or 'columns', None}}, default None
Axis to add suffix on

.. versionadded:: 1.5.0
mroeschke marked this conversation as resolved.
Show resolved Hide resolved

Returns
-------
Expand Down Expand Up @@ -4739,7 +4759,11 @@ def add_suffix(self: NDFrameT, suffix: str) -> NDFrameT:
"""
f = functools.partial("{}{suffix}".format, suffix=suffix)

mapper = {self._info_axis_name: f}
axis_name = self._info_axis_name
if axis is not None:
axis_name = self._get_axis_name(axis)

mapper = {axis_name: f}
# error: Incompatible return value type (got "Optional[NDFrameT]",
# expected "NDFrameT")
# error: Argument 1 to "rename" of "NDFrame" has incompatible type
Expand Down
73 changes: 73 additions & 0 deletions pandas/tests/frame/methods/test_add_prefix_suffix.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,3 +18,76 @@ def test_add_prefix_suffix(float_frame):
with_pct_suffix = float_frame.add_suffix("%")
expected = Index([f"{c}%" for c in float_frame.columns])
tm.assert_index_equal(with_pct_suffix.columns, expected)


def test_add_prefix_suffix_copy(float_frame):
# GH#47934
ser = float_frame.iloc[0]

with_prefix = float_frame.add_prefix("foo#", copy=True)
expected = Index([f"foo#{c}" for c in float_frame.columns])
tm.assert_index_equal(with_prefix.columns, expected)
assert not any(
tm.shares_memory(float_frame.iloc[:, i], with_prefix.iloc[:, i])
for i in range(float_frame.shape[1])
)

ser_with_prefix = ser.add_prefix("foo#", copy=True)
tm.assert_index_equal(ser_with_prefix.index, expected)
assert not tm.shares_memory(ser_with_prefix, ser)

with_prefix = float_frame.add_prefix("foo#", copy=False)
expected = Index([f"foo#{c}" for c in float_frame.columns])
tm.assert_index_equal(with_prefix.columns, expected)
assert all(
tm.shares_memory(float_frame.iloc[:, i], with_prefix.iloc[:, i])
for i in range(float_frame.shape[1])
)

ser_with_prefix = ser.add_prefix("foo#", copy=False)
tm.assert_index_equal(ser_with_prefix.index, expected)
assert tm.shares_memory(ser_with_prefix, ser)

with_suffix = float_frame.add_suffix("#foo", copy=True)
expected = Index([f"{c}#foo" for c in float_frame.columns])
tm.assert_index_equal(with_suffix.columns, expected)
assert not any(
tm.shares_memory(float_frame.iloc[:, i], with_suffix.iloc[:, i])
for i in range(float_frame.shape[1])
)

ser_with_suffix = ser.add_suffix("#foo", copy=True)
tm.assert_index_equal(ser_with_suffix.index, expected)
assert not tm.shares_memory(ser_with_suffix, ser)

with_suffix = float_frame.add_suffix("#foo", copy=False)
expected = Index([f"{c}#foo" for c in float_frame.columns])
tm.assert_index_equal(with_suffix.columns, expected)
assert all(
tm.shares_memory(float_frame.iloc[:, i], with_suffix.iloc[:, i])
for i in range(float_frame.shape[1])
)

ser_with_suffix = ser.add_suffix("#foo", copy=False)
tm.assert_index_equal(ser_with_suffix.index, expected)
assert tm.shares_memory(ser_with_suffix, ser)


def test_add_prefix_suffix_axis(float_frame):
dannyi96 marked this conversation as resolved.
Show resolved Hide resolved
# GH 47819
with_prefix = float_frame.add_prefix("foo#", axis=0)
expected = Index([f"foo#{c}" for c in float_frame.index])
tm.assert_index_equal(with_prefix.index, expected)

with_prefix = float_frame.add_prefix("foo#", axis=1)
expected = Index([f"foo#{c}" for c in float_frame.columns])
tm.assert_index_equal(with_prefix.columns, expected)

with_pct_suffix = float_frame.add_suffix("#foo", axis=0)
expected = Index([f"{c}#foo" for c in float_frame.index])
tm.assert_index_equal(with_pct_suffix.index, expected)

with_pct_suffix = float_frame.add_suffix("#foo", axis=1)
expected = Index([f"{c}#foo" for c in float_frame.columns])
tm.assert_index_equal(with_pct_suffix.columns, expected)