-
-
Notifications
You must be signed in to change notification settings - Fork 18.5k
ENH: Add replace
method to Index
#32542
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
Changes from all commits
22d53cc
47a14fa
fbbc745
5cd5d65
734c750
becbc09
ae20f64
4fa5f11
4d3ec7e
1737372
554ce48
09f3a15
f81efc1
e1711d8
1ebc201
f93adb8
0475c86
70896a7
46c4712
786208b
6dc5f8b
1512edf
241721a
be1d0ac
aeb2759
db58359
a6e01eb
0970112
1e2efc3
7bdc7a8
46d5c5a
cac074f
ff27ce4
e315717
7406775
7b4a2b0
5f86494
61b8ac5
1bb05f9
c955338
01ac22f
e6a4e8d
7d7e5ca
35d493a
b73c774
0801abf
800aef7
eb784b5
a23faaf
2a778bb
d4ade69
7fddde6
f4fa3d6
62bd25e
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -628,3 +628,24 @@ def _delegate_method(self, name: str, *args, **kwargs): | |
if is_scalar(res): | ||
return res | ||
return CategoricalIndex(res, name=self.name) | ||
|
||
def replace( | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Not adding |
||
self, | ||
to_replace=None, | ||
value=None, | ||
limit=None, | ||
regex=False, | ||
method="pad", | ||
): | ||
if regex is not False: | ||
raise NotImplementedError( | ||
"Regex replace is not yet implemented for CategoricalIndex." | ||
) | ||
|
||
new_index = self.to_series().replace( | ||
to_replace=to_replace, value=value, limit=limit, regex=regex, method=method | ||
) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. remind me why we need to disable this? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Otherwise it hits #37899. edit: That is, it hits that issue after the proposed changes due to inheritance. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. What do you think? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. So some cases will hit the same bug that affects Series.replace and other cases will work fine (assuming we don't raise here)? If so, then we're better off matching Series behavior and allowing the subset of cases that do work. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I disabled |
||
|
||
new_index = CategoricalIndex(new_index) | ||
|
||
return new_index |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,77 @@ | ||
import pytest | ||
|
||
import pandas as pd | ||
import pandas._testing as tm | ||
|
||
|
||
@pytest.mark.parametrize( | ||
"index, to_replace, value, expected", | ||
[ | ||
([1, 2, 3], [1, 3], ["a", "c"], ["a", 2, "c"]), | ||
([1, 2, 3], 1, "a", ["a", 2, 3]), | ||
( | ||
[1, None, 2], | ||
[1, 2], | ||
"a", | ||
["a", None, "a"], | ||
), | ||
], | ||
) | ||
def test_index_replace(index, to_replace, value, expected): | ||
index = pd.Index(index) | ||
expected = pd.Index(expected) | ||
|
||
result = index.replace(to_replace=to_replace, value=value) | ||
|
||
tm.assert_equal(result, expected) | ||
|
||
|
||
@pytest.mark.parametrize( | ||
"index, to_replace, value, regex, expected", | ||
[ | ||
( | ||
["bat", "foo", "baait", "bar"], | ||
r"^ba.$", | ||
"new", | ||
True, | ||
["new", "foo", "baait", "new"], | ||
), | ||
( | ||
["bat", "foo", "baait", "bar"], | ||
None, | ||
None, | ||
{r"^ba.$": "new", "foo": "xyz"}, | ||
["new", "xyz", "baait", "new"], | ||
), | ||
], | ||
) | ||
def test_index_replace_regex(index, to_replace, value, regex, expected): | ||
index = pd.Index(index) | ||
expected = pd.Index(expected) | ||
|
||
result = index.replace(to_replace=to_replace, value=value, regex=regex) | ||
tm.assert_equal(expected, result) | ||
|
||
|
||
def test_index_replace_dict_and_value(): | ||
index = pd.Index([1, 2, 3]) | ||
|
||
msg = "Series.replace cannot use dict-like to_replace and non-None value" | ||
with pytest.raises(ValueError, match=msg): | ||
index.replace({1: "a", 3: "c"}, "x") | ||
|
||
|
||
def test_index_replace_bfill(): | ||
index = pd.Index([0, 1, 2, 3, 4]) | ||
expected = pd.Index([0, 3, 3, 3, 4]) | ||
|
||
result = index.replace([1, 2], method="bfill") | ||
tm.assert_equal(expected, result) | ||
|
||
|
||
def test_index_name_preserved(): | ||
index = pd.Index(range(2), name="foo") | ||
expected = pd.Index([0, 0], name="foo") | ||
|
||
result = index.replace(1, 0) | ||
tm.assert_equal(expected, result) |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,55 @@ | ||
import pytest | ||
|
||
import pandas as pd | ||
import pandas._testing as tm | ||
|
||
|
||
@pytest.mark.parametrize( | ||
"index, to_replace, value, expected", | ||
[ | ||
([1, 2, 3], 3, "a", [1, 2, "a"]), | ||
( | ||
[1, None, 2], | ||
[1, 2], | ||
"a", | ||
["a", None, "a"], | ||
), | ||
], | ||
) | ||
def test_categorical_index_replace(index, to_replace, value, expected): | ||
index = pd.CategoricalIndex(index) | ||
expected = pd.CategoricalIndex(expected) | ||
|
||
result = index.replace(to_replace=to_replace, value=value) | ||
|
||
tm.assert_equal(result, expected) | ||
|
||
|
||
def test_categorical_index_replace_dict_and_value(): | ||
index = pd.CategoricalIndex([1, 2, 3]) | ||
|
||
msg = "Series.replace cannot use dict-like to_replace and non-None value" | ||
with pytest.raises(ValueError, match=msg): | ||
index.replace({1: "a", 3: "c"}, "x") | ||
|
||
|
||
@pytest.mark.parametrize( | ||
"index, to_replace, value, expected", | ||
[ | ||
([1, 2, 3], [2, 3], ["b", "c"], [1, "b", "c"]), | ||
([1, 2, 3], 3, "c", [1, 2, "c"]), | ||
( | ||
[1, None, 2], | ||
[1, 2], | ||
"a", | ||
["a", None, "a"], | ||
), | ||
], | ||
) | ||
def test_index_replace(index, to_replace, value, expected): | ||
index = pd.CategoricalIndex(index) | ||
expected = pd.CategoricalIndex(expected) | ||
|
||
result = index.replace(to_replace=to_replace, value=value) | ||
|
||
tm.assert_equal(result, expected) |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,70 @@ | ||
import pytest | ||
|
||
import pandas as pd | ||
import pandas._testing as tm | ||
|
||
|
||
@pytest.mark.parametrize( | ||
"names, arrays, to_replace, value, expected_arrays", | ||
[ | ||
( | ||
[None, None], | ||
[[1, 1, 2, 2], ["red", "blue", "red", "blue"]], | ||
[1, "red"], | ||
[0, "black"], | ||
[[0, 0, 2, 2], ["black", "blue", "black", "blue"]], | ||
), | ||
# names should be preserved | ||
( | ||
["digits", "colors"], | ||
[[1, 1, 2, 2], ["red", "blue", "red", "blue"]], | ||
1, | ||
0, | ||
[[0, 0, 2, 2], ["red", "blue", "red", "blue"]], | ||
), | ||
( | ||
[None, None], | ||
[[1, 1, 2, 2], ["red", "blue", "red", "blue"]], | ||
1, | ||
0, | ||
[[0, 0, 2, 2], ["red", "blue", "red", "blue"]], | ||
), | ||
( | ||
[None, None], | ||
[[1, 1, 2, 2], ["red", "blue", "red", "blue"]], | ||
[1, 2], | ||
0, | ||
[[0, 0, 0, 0], ["red", "blue", "red", "blue"]], | ||
), | ||
( | ||
[None, None], | ||
[[1, 1, 2, 2], ["red", "blue", "red", "blue"]], | ||
[1, 2], | ||
0, | ||
[[0, 0, 0, 0], ["red", "blue", "red", "blue"]], | ||
), | ||
# nested dicts | ||
( | ||
["digits", "colors"], | ||
[[1, 1, 2, 2], ["red", "blue", "red", "blue"]], | ||
{"digits": {1: 0}, "colors": {"red": "black"}}, | ||
None, | ||
[[0, 0, 2, 2], ["black", "blue", "black", "blue"]], | ||
), | ||
# dicts and value | ||
( | ||
["digits", "colors"], | ||
[[1, 1, 2, 2], ["red", "blue", "red", "blue"]], | ||
{"digits": [1], "colors": ["red", "blue"]}, | ||
"x", | ||
[["x", "x", 2, 2], ["x", "x", "x", "x"]], | ||
), | ||
], | ||
) | ||
def test_multi_index_replace(names, arrays, to_replace, value, expected_arrays): | ||
multi_index = pd.MultiIndex.from_arrays(arrays, names=names) | ||
expected = pd.MultiIndex.from_arrays(expected_arrays, names=names) | ||
|
||
result = multi_index.replace(to_replace=to_replace, value=value) | ||
|
||
tm.assert_equal(result, expected) |
Uh oh!
There was an error while loading. Please reload this page.