From 258ec02a0c443821eb7300d3210ee44c4853d6d5 Mon Sep 17 00:00:00 2001 From: "JHM Darbyshire (iMac)" Date: Thu, 25 Mar 2021 21:51:25 +0100 Subject: [PATCH 1/5] styler.where kwargs fix. --- pandas/io/formats/style.py | 23 ++++++++++++++++------- 1 file changed, 16 insertions(+), 7 deletions(-) diff --git a/pandas/io/formats/style.py b/pandas/io/formats/style.py index 9250d861740fc..b58d39bb595cd 100644 --- a/pandas/io/formats/style.py +++ b/pandas/io/formats/style.py @@ -1079,7 +1079,7 @@ def where( Parameters ---------- cond : callable - ``cond`` should take a scalar and return a boolean. + ``cond`` should take a scalar, and optional args, and return a boolean. value : str Applied when ``cond`` returns true. other : str @@ -1099,18 +1099,27 @@ def where( Styler.applymap: Apply a CSS-styling function elementwise. Styler.apply: Apply a CSS-styling function column-wise, row-wise, or table-wise. - Examples - -------- - >>> def cond(v): - ... return v > 1 and v != 4 + Notes + ----- + This method is a convenience wrapper for :meth:`Styler.applymap`, which we + recommend using instead. + + Instead of the example: >>> df = pd.DataFrame([[1, 2], [3, 4]]) - >>> df.style.where(cond, value='color:red;', other='font-size:2em;') + >>> def cond(v, bad_val=4): + ... return v > 1 and v != bad_val + >>> df.style.where(cond, value='color:green;', other='color:red;') + + we would recommend: + >>> def style_func(v, good_css, bad_css, bad_val=4): + ... return good_css if v > 1 and v != bad_val else bad_css + >>> df.style.applymap(style_func, good_css='color:green;', bad_css='color:red;') """ if other is None: other = "" return self.applymap( - lambda val: value if cond(val) else other, subset=subset, **kwargs + lambda val: value if cond(val, **kwargs) else other, subset=subset ) def set_precision(self, precision: int) -> Styler: From 7fe032f6a65e04dc06ac5ef5042528dfe7aa818e Mon Sep 17 00:00:00 2001 From: "JHM Darbyshire (MBP)" Date: Sat, 27 Mar 2021 09:40:37 +0100 Subject: [PATCH 2/5] kwargs test --- pandas/tests/io/formats/style/test_style.py | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/pandas/tests/io/formats/style/test_style.py b/pandas/tests/io/formats/style/test_style.py index 302019b702829..c79d140f3b8a0 100644 --- a/pandas/tests/io/formats/style/test_style.py +++ b/pandas/tests/io/formats/style/test_style.py @@ -552,6 +552,21 @@ def g(x): expected = self.df.style.applymap(g, subset=slice_)._compute().ctx assert result == expected + def test_where_kwargs(self): + df = DataFrame([[1, 2], [3, 4]]) + + def f(x, val): + return x > val + + result = df.style.where(f, 'color:green;', 'color:red;', val=2)._compute().ctx + expected = { + (0, 0): [('color', 'red')], + (0, 1): [('color', 'red')], + (1, 0): [('color', 'green')], + (1, 1): [('color', 'green')], + } + assert result == expected + def test_empty(self): df = DataFrame({"A": [1, 0]}) s = df.style From ea082b5f22913d45002b7442693048854ce28bd5 Mon Sep 17 00:00:00 2001 From: "JHM Darbyshire (MBP)" Date: Sat, 27 Mar 2021 18:16:59 +0100 Subject: [PATCH 3/5] introduce deprecatation warnings --- pandas/io/formats/style.py | 27 +++++++++++++------- pandas/tests/io/formats/style/test_style.py | 28 ++++++++++++--------- 2 files changed, 34 insertions(+), 21 deletions(-) diff --git a/pandas/io/formats/style.py b/pandas/io/formats/style.py index b58d39bb595cd..3c18a3df09060 100644 --- a/pandas/io/formats/style.py +++ b/pandas/io/formats/style.py @@ -983,7 +983,6 @@ def apply( See Also -------- - Styler.where: Apply CSS-styles based on a conditional function elementwise. Styler.applymap: Apply a CSS-styling function elementwise. Notes @@ -1041,7 +1040,6 @@ def applymap(self, func: Callable, subset=None, **kwargs) -> Styler: See Also -------- - Styler.where: Apply CSS-styles based on a conditional function elementwise. Styler.apply: Apply a CSS-styling function column-wise, row-wise, or table-wise. Notes @@ -1076,6 +1074,8 @@ def where( Updates the HTML representation with a style which is selected in accordance with the return value of a function. + .. deprecated:: 1.3.0 + Parameters ---------- cond : callable @@ -1101,20 +1101,29 @@ def where( Notes ----- + This method is deprecated. + This method is a convenience wrapper for :meth:`Styler.applymap`, which we recommend using instead. - Instead of the example: + The example: >>> df = pd.DataFrame([[1, 2], [3, 4]]) - >>> def cond(v, bad_val=4): - ... return v > 1 and v != bad_val + >>> def cond(v, limit=4): + ... return v > 1 and v != limit >>> df.style.where(cond, value='color:green;', other='color:red;') - we would recommend: - >>> def style_func(v, good_css, bad_css, bad_val=4): - ... return good_css if v > 1 and v != bad_val else bad_css - >>> df.style.applymap(style_func, good_css='color:green;', bad_css='color:red;') + should be refactored to: + >>> def style_func(v, value, other, limit=4): + ... cond = v > 1 and v != limit + ... return value if cond else other + >>> df.style.applymap(style_func, value='color:green;', other='color:red;') """ + warnings.warn( + "this method is deprecated in favour of `Styler.applymap()`", + FutureWarning, + stacklevel=2, + ) + if other is None: other = "" diff --git a/pandas/tests/io/formats/style/test_style.py b/pandas/tests/io/formats/style/test_style.py index c79d140f3b8a0..38a1d3b228fe3 100644 --- a/pandas/tests/io/formats/style/test_style.py +++ b/pandas/tests/io/formats/style/test_style.py @@ -490,7 +490,8 @@ def f(x): style1 = "foo: bar" - result = self.df.style.where(f, style1)._compute().ctx + with tm.assert_produces_warning(FutureWarning): + result = self.df.style.where(f, style1)._compute().ctx expected = { (r, c): [("foo", "bar")] for r, row in enumerate(self.df.index) @@ -517,14 +518,15 @@ def f(x): style1 = "foo: bar" style2 = "baz: foo" - result = self.df.style.where(f, style1, style2, subset=slice_)._compute().ctx + with tm.assert_produces_warning(FutureWarning): + res = self.df.style.where(f, style1, style2, subset=slice_)._compute().ctx expected = { (r, c): [("foo", "bar") if f(self.df.loc[row, col]) else ("baz", "foo")] for r, row in enumerate(self.df.index) for c, col in enumerate(self.df.columns) if row in self.df.loc[slice_].index and col in self.df.loc[slice_].columns } - assert result == expected + assert res == expected def test_where_subset_compare_with_applymap(self): # GH 17474 @@ -546,9 +548,10 @@ def g(x): ] for slice_ in slices: - result = ( - self.df.style.where(f, style1, style2, subset=slice_)._compute().ctx - ) + with tm.assert_produces_warning(FutureWarning): + result = ( + self.df.style.where(f, style1, style2, subset=slice_)._compute().ctx + ) expected = self.df.style.applymap(g, subset=slice_)._compute().ctx assert result == expected @@ -558,14 +561,15 @@ def test_where_kwargs(self): def f(x, val): return x > val - result = df.style.where(f, 'color:green;', 'color:red;', val=2)._compute().ctx + with tm.assert_produces_warning(FutureWarning): + res = df.style.where(f, "color:green;", "color:red;", val=2)._compute().ctx expected = { - (0, 0): [('color', 'red')], - (0, 1): [('color', 'red')], - (1, 0): [('color', 'green')], - (1, 1): [('color', 'green')], + (0, 0): [("color", "red")], + (0, 1): [("color", "red")], + (1, 0): [("color", "green")], + (1, 1): [("color", "green")], } - assert result == expected + assert res == expected def test_empty(self): df = DataFrame({"A": [1, 0]}) From aa56f95308b84539409c87890f666de0c94d7a57 Mon Sep 17 00:00:00 2001 From: "JHM Darbyshire (MBP)" Date: Sat, 10 Apr 2021 08:00:19 +0200 Subject: [PATCH 4/5] fix --- pandas/io/formats/style.py | 1 - 1 file changed, 1 deletion(-) diff --git a/pandas/io/formats/style.py b/pandas/io/formats/style.py index 24ce5e66fa7ef..b6fbc55b27c6f 100644 --- a/pandas/io/formats/style.py +++ b/pandas/io/formats/style.py @@ -1086,7 +1086,6 @@ def where( Parameters ---------- cond : callable - ``cond`` should take a scalar, and optional args, and return a boolean. ``cond`` should take a scalar, and optional keyword arguments, and return a boolean. value : str From 1f922376c7ebf22a128fef11010273fb285fc656 Mon Sep 17 00:00:00 2001 From: "JHM Darbyshire (MBP)" Date: Sat, 10 Apr 2021 13:32:12 +0200 Subject: [PATCH 5/5] Merge branch 'basic_subclassing_styler' into latex_styler_mvp # Conflicts: # pandas/io/formats/style.py --- pandas/io/formats/style.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pandas/io/formats/style.py b/pandas/io/formats/style.py index b6fbc55b27c6f..806dea8001fcd 100644 --- a/pandas/io/formats/style.py +++ b/pandas/io/formats/style.py @@ -1078,11 +1078,11 @@ def where( """ Apply CSS-styles based on a conditional function elementwise. + .. deprecated:: 1.3.0 + Updates the HTML representation with a style which is selected in accordance with the return value of a function. - .. deprecated:: 1.3.0 - Parameters ---------- cond : callable