Skip to content

Commit fa3dbc1

Browse files
committed
Merge remote-tracking branch 'upstream/master' into rdata_c
2 parents 0ab02ec + bb5bfa6 commit fa3dbc1

File tree

3 files changed

+62
-128
lines changed

3 files changed

+62
-128
lines changed

doc/source/whatsnew/v1.3.0.rst

+1
Original file line numberDiff line numberDiff line change
@@ -326,6 +326,7 @@ Other enhancements
326326
- :meth:`pandas.read_csv` and :meth:`pandas.read_json` expose the argument ``encoding_errors`` to control how encoding errors are handled (:issue:`39450`)
327327
- :meth:`.GroupBy.any` and :meth:`.GroupBy.all` use Kleene logic with nullable data types (:issue:`37506`)
328328
- :meth:`.GroupBy.any` and :meth:`.GroupBy.all` return a ``BooleanDtype`` for columns with nullable data types (:issue:`33449`)
329+
- :meth:`.GroupBy.rank` now supports object-dtype data (:issue:`38278`)
329330
- Constructing a :class:`DataFrame` or :class:`Series` with the ``data`` argument being a Python iterable that is *not* a NumPy ``ndarray`` consisting of NumPy scalars will now result in a dtype with a precision the maximum of the NumPy scalars; this was already the case when ``data`` is a NumPy ``ndarray`` (:issue:`40908`)
330331
- Add keyword ``sort`` to :func:`pivot_table` to allow non-sorting of the result (:issue:`39143`)
331332
- Add keyword ``dropna`` to :meth:`DataFrame.value_counts` to allow counting rows that include ``NA`` values (:issue:`41325`)

pandas/core/frame.py

+9-8
Original file line numberDiff line numberDiff line change
@@ -8923,6 +8923,7 @@ def append(
89238923
Returns
89248924
-------
89258925
DataFrame
8926+
A new DataFrame consisting of the rows of caller and the rows of `other`.
89268927
89278928
See Also
89288929
--------
@@ -8941,18 +8942,18 @@ def append(
89418942
89428943
Examples
89438944
--------
8944-
>>> df = pd.DataFrame([[1, 2], [3, 4]], columns=list('AB'))
8945+
>>> df = pd.DataFrame([[1, 2], [3, 4]], columns=list('AB'), index=['x', 'y'])
89458946
>>> df
89468947
A B
8947-
0 1 2
8948-
1 3 4
8949-
>>> df2 = pd.DataFrame([[5, 6], [7, 8]], columns=list('AB'))
8948+
x 1 2
8949+
y 3 4
8950+
>>> df2 = pd.DataFrame([[5, 6], [7, 8]], columns=list('AB'), index=['x', 'y'])
89508951
>>> df.append(df2)
89518952
A B
8952-
0 1 2
8953-
1 3 4
8954-
0 5 6
8955-
1 7 8
8953+
x 1 2
8954+
y 3 4
8955+
x 5 6
8956+
y 7 8
89568957
89578958
With `ignore_index` set to True:
89588959

pandas/tests/frame/methods/test_replace.py

+52-120
Original file line numberDiff line numberDiff line change
@@ -57,129 +57,61 @@ def test_replace_inplace(self, datetime_frame, float_string_frame):
5757
assert return_value is None
5858
tm.assert_frame_equal(tsframe, datetime_frame.fillna(0))
5959

60-
def test_regex_replace_list_obj(self):
61-
obj = {"a": list("ab.."), "b": list("efgh"), "c": list("helo")}
62-
dfobj = DataFrame(obj)
63-
64-
# lists of regexes and values
65-
# list of [re1, re2, ..., reN] -> [v1, v2, ..., vN]
66-
to_replace_res = [r"\s*\.\s*", r"e|f|g"]
67-
values = [np.nan, "crap"]
68-
res = dfobj.replace(to_replace_res, values, regex=True)
69-
expec = DataFrame(
70-
{
71-
"a": ["a", "b", np.nan, np.nan],
72-
"b": ["crap"] * 3 + ["h"],
73-
"c": ["h", "crap", "l", "o"],
74-
}
75-
)
76-
tm.assert_frame_equal(res, expec)
77-
78-
# list of [re1, re2, ..., reN] -> [re1, re2, .., reN]
79-
to_replace_res = [r"\s*(\.)\s*", r"(e|f|g)"]
80-
values = [r"\1\1", r"\1_crap"]
81-
res = dfobj.replace(to_replace_res, values, regex=True)
82-
expec = DataFrame(
83-
{
84-
"a": ["a", "b", "..", ".."],
85-
"b": ["e_crap", "f_crap", "g_crap", "h"],
86-
"c": ["h", "e_crap", "l", "o"],
87-
}
88-
)
89-
tm.assert_frame_equal(res, expec)
90-
91-
# list of [re1, re2, ..., reN] -> [(re1 or v1), (re2 or v2), ..., (reN
92-
# or vN)]
93-
to_replace_res = [r"\s*(\.)\s*", r"e"]
94-
values = [r"\1\1", r"crap"]
95-
res = dfobj.replace(to_replace_res, values, regex=True)
96-
expec = DataFrame(
97-
{
98-
"a": ["a", "b", "..", ".."],
99-
"b": ["crap", "f", "g", "h"],
100-
"c": ["h", "crap", "l", "o"],
101-
}
102-
)
103-
tm.assert_frame_equal(res, expec)
104-
105-
to_replace_res = [r"\s*(\.)\s*", r"e"]
106-
values = [r"\1\1", r"crap"]
107-
res = dfobj.replace(value=values, regex=to_replace_res)
108-
expec = DataFrame(
109-
{
110-
"a": ["a", "b", "..", ".."],
111-
"b": ["crap", "f", "g", "h"],
112-
"c": ["h", "crap", "l", "o"],
113-
}
114-
)
115-
tm.assert_frame_equal(res, expec)
116-
117-
def test_regex_replace_list_obj_inplace(self):
118-
# same as above with inplace=True
119-
# lists of regexes and values
120-
obj = {"a": list("ab.."), "b": list("efgh"), "c": list("helo")}
121-
dfobj = DataFrame(obj)
122-
123-
# lists of regexes and values
124-
# list of [re1, re2, ..., reN] -> [v1, v2, ..., vN]
125-
to_replace_res = [r"\s*\.\s*", r"e|f|g"]
126-
values = [np.nan, "crap"]
127-
res = dfobj.copy()
128-
return_value = res.replace(to_replace_res, values, inplace=True, regex=True)
129-
assert return_value is None
130-
expec = DataFrame(
131-
{
132-
"a": ["a", "b", np.nan, np.nan],
133-
"b": ["crap"] * 3 + ["h"],
134-
"c": ["h", "crap", "l", "o"],
135-
}
136-
)
137-
tm.assert_frame_equal(res, expec)
60+
@pytest.mark.parametrize(
61+
"to_replace,values,expected",
62+
[
63+
# lists of regexes and values
64+
# list of [re1, re2, ..., reN] -> [v1, v2, ..., vN]
65+
(
66+
[r"\s*\.\s*", r"e|f|g"],
67+
[np.nan, "crap"],
68+
{
69+
"a": ["a", "b", np.nan, np.nan],
70+
"b": ["crap"] * 3 + ["h"],
71+
"c": ["h", "crap", "l", "o"],
72+
},
73+
),
74+
# list of [re1, re2, ..., reN] -> [re1, re2, .., reN]
75+
(
76+
[r"\s*(\.)\s*", r"(e|f|g)"],
77+
[r"\1\1", r"\1_crap"],
78+
{
79+
"a": ["a", "b", "..", ".."],
80+
"b": ["e_crap", "f_crap", "g_crap", "h"],
81+
"c": ["h", "e_crap", "l", "o"],
82+
},
83+
),
84+
# list of [re1, re2, ..., reN] -> [(re1 or v1), (re2 or v2), ..., (reN
85+
# or vN)]
86+
(
87+
[r"\s*(\.)\s*", r"e"],
88+
[r"\1\1", r"crap"],
89+
{
90+
"a": ["a", "b", "..", ".."],
91+
"b": ["crap", "f", "g", "h"],
92+
"c": ["h", "crap", "l", "o"],
93+
},
94+
),
95+
],
96+
)
97+
@pytest.mark.parametrize("inplace", [True, False])
98+
@pytest.mark.parametrize("use_value_regex_args", [True, False])
99+
def test_regex_replace_list_obj(
100+
self, to_replace, values, expected, inplace, use_value_regex_args
101+
):
102+
df = DataFrame({"a": list("ab.."), "b": list("efgh"), "c": list("helo")})
138103

139-
# list of [re1, re2, ..., reN] -> [re1, re2, .., reN]
140-
to_replace_res = [r"\s*(\.)\s*", r"(e|f|g)"]
141-
values = [r"\1\1", r"\1_crap"]
142-
res = dfobj.copy()
143-
return_value = res.replace(to_replace_res, values, inplace=True, regex=True)
144-
assert return_value is None
145-
expec = DataFrame(
146-
{
147-
"a": ["a", "b", "..", ".."],
148-
"b": ["e_crap", "f_crap", "g_crap", "h"],
149-
"c": ["h", "e_crap", "l", "o"],
150-
}
151-
)
152-
tm.assert_frame_equal(res, expec)
104+
if use_value_regex_args:
105+
result = df.replace(value=values, regex=to_replace, inplace=inplace)
106+
else:
107+
result = df.replace(to_replace, values, regex=True, inplace=inplace)
153108

154-
# list of [re1, re2, ..., reN] -> [(re1 or v1), (re2 or v2), ..., (reN
155-
# or vN)]
156-
to_replace_res = [r"\s*(\.)\s*", r"e"]
157-
values = [r"\1\1", r"crap"]
158-
res = dfobj.copy()
159-
return_value = res.replace(to_replace_res, values, inplace=True, regex=True)
160-
assert return_value is None
161-
expec = DataFrame(
162-
{
163-
"a": ["a", "b", "..", ".."],
164-
"b": ["crap", "f", "g", "h"],
165-
"c": ["h", "crap", "l", "o"],
166-
}
167-
)
168-
tm.assert_frame_equal(res, expec)
109+
if inplace:
110+
assert result is None
111+
result = df
169112

170-
to_replace_res = [r"\s*(\.)\s*", r"e"]
171-
values = [r"\1\1", r"crap"]
172-
res = dfobj.copy()
173-
return_value = res.replace(value=values, regex=to_replace_res, inplace=True)
174-
assert return_value is None
175-
expec = DataFrame(
176-
{
177-
"a": ["a", "b", "..", ".."],
178-
"b": ["crap", "f", "g", "h"],
179-
"c": ["h", "crap", "l", "o"],
180-
}
181-
)
182-
tm.assert_frame_equal(res, expec)
113+
expected = DataFrame(expected)
114+
tm.assert_frame_equal(result, expected)
183115

184116
def test_regex_replace_list_mixed(self, mix_ab):
185117
# mixed frame to make sure this doesn't break things

0 commit comments

Comments
 (0)