Skip to content

Commit 8276a56

Browse files
authored
DEPR: Silent dropping of nuisance columns in transform_dict_like (#43743)
1 parent befbc47 commit 8276a56

File tree

4 files changed

+39
-20
lines changed

4 files changed

+39
-20
lines changed

doc/source/whatsnew/v1.4.0.rst

+1
Original file line numberDiff line numberDiff line change
@@ -337,6 +337,7 @@ Other Deprecations
337337
- Deprecated the ``squeeze`` argument to :meth:`read_csv`, :meth:`read_table`, and :meth:`read_excel`. Users should squeeze the DataFrame afterwards with ``.squeeze("columns")`` instead. (:issue:`43242`)
338338
- Deprecated the ``index`` argument to :class:`SparseArray` construction (:issue:`23089`)
339339
- Deprecated :meth:`.Rolling.validate`, :meth:`.Expanding.validate`, and :meth:`.ExponentialMovingWindow.validate` (:issue:`43665`)
340+
- Deprecated silent dropping of columns that raised a ``TypeError`` in :class:`Series.transform` and :class:`DataFrame.transform` when used with a dictionary (:issue:`43740`)
340341

341342
.. ---------------------------------------------------------------------------
342343

pandas/core/apply.py

+7-6
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@
3333
FrameOrSeries,
3434
)
3535
from pandas.util._decorators import cache_readonly
36+
from pandas.util._exceptions import find_stack_level
3637

3738
from pandas.core.dtypes.cast import is_nested_object
3839
from pandas.core.dtypes.common import (
@@ -271,21 +272,21 @@ def transform_dict_like(self, func):
271272
"No transform functions were provided",
272273
}:
273274
raise err
274-
elif not isinstance(err, TypeError):
275-
all_type_errors = False
275+
else:
276+
if not isinstance(err, TypeError):
277+
all_type_errors = False
276278
failed_names.append(name)
277279
# combine results
278280
if not results:
279281
klass = TypeError if all_type_errors else ValueError
280282
raise klass("Transform function failed")
281283
if len(failed_names) > 0:
282284
warnings.warn(
283-
f"{failed_names} did not transform successfully and did not raise "
284-
f"a TypeError. If any error is raised except for TypeError, "
285-
f"this will raise in a future version of pandas. "
285+
f"{failed_names} did not transform successfully. If any error is "
286+
f"raised, this will raise in a future version of pandas. "
286287
f"Drop these columns/ops to avoid this warning.",
287288
FutureWarning,
288-
stacklevel=4,
289+
stacklevel=find_stack_level(),
289290
)
290291
return concat(results, axis=1)
291292

pandas/tests/apply/test_frame_transform.py

+14-7
Original file line numberDiff line numberDiff line change
@@ -160,33 +160,40 @@ def test_transform_bad_dtype(op, frame_or_series, request):
160160
@pytest.mark.parametrize("op", frame_kernels_raise)
161161
def test_transform_partial_failure_typeerror(op):
162162
# GH 35964
163-
164163
if op == "rank":
165164
pytest.skip("GH 40418: rank does not raise a TypeError")
166165

167166
# Using object makes most transform kernels fail
168167
df = DataFrame({"A": 3 * [object], "B": [1, 2, 3]})
169168

170169
expected = df[["B"]].transform([op])
171-
result = df.transform([op])
170+
match = r"\['A'\] did not transform successfully"
171+
with tm.assert_produces_warning(FutureWarning, match=match):
172+
result = df.transform([op])
172173
tm.assert_equal(result, expected)
173174

174175
expected = df[["B"]].transform({"B": op})
175-
result = df.transform({"A": op, "B": op})
176+
match = r"\['A'\] did not transform successfully"
177+
with tm.assert_produces_warning(FutureWarning, match=match):
178+
result = df.transform({"A": op, "B": op})
176179
tm.assert_equal(result, expected)
177180

178181
expected = df[["B"]].transform({"B": [op]})
179-
result = df.transform({"A": [op], "B": [op]})
182+
match = r"\['A'\] did not transform successfully"
183+
with tm.assert_produces_warning(FutureWarning, match=match):
184+
result = df.transform({"A": [op], "B": [op]})
180185
tm.assert_equal(result, expected)
181186

182187
expected = df.transform({"A": ["shift"], "B": [op]})
183-
result = df.transform({"A": [op, "shift"], "B": [op]})
188+
match = rf"\['{op}'\] did not transform successfully"
189+
with tm.assert_produces_warning(FutureWarning, match=match):
190+
result = df.transform({"A": [op, "shift"], "B": [op]})
184191
tm.assert_equal(result, expected)
185192

186193

187194
def test_transform_partial_failure_valueerror():
188195
# GH 40211
189-
match = ".*did not transform successfully and did not raise a TypeError"
196+
match = ".*did not transform successfully"
190197

191198
def op(x):
192199
if np.sum(np.sum(x)) < 10:
@@ -211,7 +218,7 @@ def op(x):
211218
tm.assert_equal(result, expected)
212219

213220
expected = df.transform({"A": ["shift"], "B": [op]})
214-
with tm.assert_produces_warning(FutureWarning, match=match, check_stacklevel=False):
221+
with tm.assert_produces_warning(FutureWarning, match=match):
215222
result = df.transform({"A": [op, "shift"], "B": [op]})
216223
tm.assert_equal(result, expected)
217224

pandas/tests/apply/test_series_apply.py

+17-7
Original file line numberDiff line numberDiff line change
@@ -291,25 +291,35 @@ def test_transform_partial_failure(op, request):
291291
ser = Series(3 * [object])
292292

293293
expected = ser.transform(["shift"])
294-
result = ser.transform([op, "shift"])
294+
match = rf"\['{op}'\] did not transform successfully"
295+
with tm.assert_produces_warning(FutureWarning, match=match):
296+
result = ser.transform([op, "shift"])
295297
tm.assert_equal(result, expected)
296298

297299
expected = ser.transform({"B": "shift"})
298-
result = ser.transform({"A": op, "B": "shift"})
300+
match = r"\['A'\] did not transform successfully"
301+
with tm.assert_produces_warning(FutureWarning, match=match):
302+
result = ser.transform({"A": op, "B": "shift"})
299303
tm.assert_equal(result, expected)
300304

301305
expected = ser.transform({"B": ["shift"]})
302-
result = ser.transform({"A": [op], "B": ["shift"]})
306+
match = r"\['A'\] did not transform successfully"
307+
with tm.assert_produces_warning(FutureWarning, match=match):
308+
result = ser.transform({"A": [op], "B": ["shift"]})
303309
tm.assert_equal(result, expected)
304310

305-
expected = ser.transform({"A": ["shift"], "B": [op]})
306-
result = ser.transform({"A": [op, "shift"], "B": [op]})
311+
match = r"\['B'\] did not transform successfully"
312+
with tm.assert_produces_warning(FutureWarning, match=match):
313+
expected = ser.transform({"A": ["shift"], "B": [op]})
314+
match = rf"\['{op}'\] did not transform successfully"
315+
with tm.assert_produces_warning(FutureWarning, match=match):
316+
result = ser.transform({"A": [op, "shift"], "B": [op]})
307317
tm.assert_equal(result, expected)
308318

309319

310320
def test_transform_partial_failure_valueerror():
311321
# GH 40211
312-
match = ".*did not transform successfully and did not raise a TypeError"
322+
match = ".*did not transform successfully"
313323

314324
def noop(x):
315325
return x
@@ -335,7 +345,7 @@ def raising_op(_):
335345
tm.assert_equal(result, expected)
336346

337347
expected = ser.transform({"A": [noop], "B": [noop]})
338-
with tm.assert_produces_warning(FutureWarning, match=match, check_stacklevel=False):
348+
with tm.assert_produces_warning(FutureWarning, match=match):
339349
result = ser.transform({"A": [noop, raising_op], "B": [noop]})
340350
tm.assert_equal(result, expected)
341351

0 commit comments

Comments
 (0)