Skip to content

Commit ef9cfcc

Browse files
committed
fix conflict from clip inplace
1 parent e81f3cc commit ef9cfcc

File tree

3 files changed

+68
-20
lines changed

3 files changed

+68
-20
lines changed

pandas/core/generic.py

Lines changed: 37 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -4287,6 +4287,39 @@ def _clip_with_scalar(self, lower, upper, inplace=False):
42874287
else:
42884288
return result
42894289

4290+
def _clip_with_one_bound(self, threshold, method, axis, inplace):
4291+
4292+
if np.any(isnull(threshold)):
4293+
raise ValueError("Cannot use an NA value as a clip threshold")
4294+
4295+
# method is self.le for upper bound and self.ge for lower bound
4296+
if is_scalar(threshold) and is_number(threshold):
4297+
if method.__name__ == 'le':
4298+
return self._clip_with_scalar(None, threshold, inplace=inplace)
4299+
else:
4300+
return self._clip_with_scalar(threshold, None, inplace=inplace)
4301+
4302+
inplace = validate_bool_kwarg(inplace, 'inplace')
4303+
4304+
subset = method(threshold, axis=axis) | isnull(self)
4305+
4306+
# GH #15390
4307+
if is_scalar(threshold) or is_number(threshold):
4308+
return self.where(subset, threshold, axis=axis, inplace=inplace)
4309+
4310+
# For arry_like threshold, convet it to Series with corret index
4311+
# `where` only takes
4312+
try:
4313+
if isinstance(subset, ABCSeries):
4314+
threshold = pd.Series(threshold, index=subset.index)
4315+
elif axis == 0:
4316+
threshold = pd.Series(threshold, index=subset.index)
4317+
else:
4318+
threshold = pd.Series(threshold, index=subset.columns)
4319+
finally:
4320+
return self.where(subset, threshold, axis=axis, inplace=inplace)
4321+
4322+
42904323
def clip(self, lower=None, upper=None, axis=None, inplace=False,
42914324
*args, **kwargs):
42924325
"""
@@ -4389,16 +4422,8 @@ def clip_upper(self, threshold, axis=None, inplace=False):
43894422
-------
43904423
clipped : same type as input
43914424
"""
4392-
if np.any(isnull(threshold)):
4393-
raise ValueError("Cannot use an NA value as a clip threshold")
4394-
4395-
if is_scalar(threshold) and is_number(threshold):
4396-
return self._clip_with_scalar(None, threshold, inplace=inplace)
4397-
4398-
inplace = validate_bool_kwarg(inplace, 'inplace')
4399-
4400-
subset = self.le(threshold, axis=axis) | isnull(self)
4401-
return self.where(subset, threshold, axis=axis, inplace=inplace)
4425+
return self._clip_with_one_bound(threshold, method=self.le,
4426+
axis=axis, inplace=inplace)
44024427

44034428
def clip_lower(self, threshold, axis=None, inplace=False):
44044429
"""
@@ -4421,16 +4446,8 @@ def clip_lower(self, threshold, axis=None, inplace=False):
44214446
-------
44224447
clipped : same type as input
44234448
"""
4424-
if np.any(isnull(threshold)):
4425-
raise ValueError("Cannot use an NA value as a clip threshold")
4426-
4427-
if is_scalar(threshold) and is_number(threshold):
4428-
return self._clip_with_scalar(threshold, None, inplace=inplace)
4429-
4430-
inplace = validate_bool_kwarg(inplace, 'inplace')
4431-
4432-
subset = self.ge(threshold, axis=axis) | isnull(self)
4433-
return self.where(subset, threshold, axis=axis, inplace=inplace)
4449+
return self._clip_with_one_bound(threshold, method=self.ge,
4450+
axis=axis, inplace=inplace)
44344451

44354452
def groupby(self, by=None, axis=0, level=None, as_index=True, sort=True,
44364453
group_keys=True, squeeze=False, **kwargs):

pandas/tests/frame/test_analytics.py

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1892,6 +1892,25 @@ def test_clip_against_series(self, inplace):
18921892

18931893
tm.assert_series_equal(clipped_df.loc[mask, i], df.loc[mask, i])
18941894

1895+
@pytest.mark.parametrize("inplace", [True, False])
1896+
def test_clip_against_list(self, inplace):
1897+
# GH #15390
1898+
original = self.simple
1899+
1900+
result = original.clip(lower=[2, 3, 4], upper=[5, 6, 7],
1901+
axis=1, inplace=inplace)
1902+
1903+
arr = np.array([[2., 3., 4.],
1904+
[4., 5., 6.],
1905+
[5., 6., 7.]])
1906+
expected = pd.DataFrame(arr,
1907+
columns=original.columns,
1908+
index=original.index)
1909+
if inplace:
1910+
tm.assert_frame_equal(original, expected, check_exact=True)
1911+
else:
1912+
tm.assert_frame_equal(result, expected, check_exact=True)
1913+
18951914
def test_clip_against_frame(self):
18961915
df = DataFrame(np.random.randn(1000, 2))
18971916
lb = DataFrame(np.random.randn(1000, 2))

pandas/tests/series/test_analytics.py

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1015,6 +1015,18 @@ def test_clip_against_series(self):
10151015
assert_series_equal(s.clip(lower, upper), Series([1.0, 2.0, 3.5]))
10161016
assert_series_equal(s.clip(1.5, upper), Series([1.5, 1.5, 3.5]))
10171017

1018+
@pytest.mark.parametrize("inplace", [True, False])
1019+
def test_clip_against_list(self, inplace):
1020+
# GH #15390
1021+
original = pd.Series([5, 6, 7])
1022+
result = original.clip(upper=[1, 2, 3], inplace=inplace)
1023+
expected = pd.Series([1, 2, 3])
1024+
1025+
if inplace:
1026+
tm.assert_series_equal(original, expected, check_exact=True)
1027+
else:
1028+
tm.assert_series_equal(result, expected, check_exact=True)
1029+
10181030
def test_clip_with_datetimes(self):
10191031

10201032
# GH 11838

0 commit comments

Comments
 (0)