From 51c4ac0507360b29f4372781f8f0873a120321b2 Mon Sep 17 00:00:00 2001 From: "JHM Darbyshire (iMac)" Date: Sun, 21 Feb 2021 00:22:16 +0100 Subject: [PATCH 1/7] refactor styler tests --- pandas/tests/io/formats/style/__init__.py | 0 .../tests/io/formats/style/test_builtins.py | 656 ++++++++++++++++++ .../io/formats/{ => style}/test_style.py | 646 ----------------- 3 files changed, 656 insertions(+), 646 deletions(-) create mode 100644 pandas/tests/io/formats/style/__init__.py create mode 100644 pandas/tests/io/formats/style/test_builtins.py rename pandas/tests/io/formats/{ => style}/test_style.py (69%) diff --git a/pandas/tests/io/formats/style/__init__.py b/pandas/tests/io/formats/style/__init__.py new file mode 100644 index 0000000000000..e69de29bb2d1d diff --git a/pandas/tests/io/formats/style/test_builtins.py b/pandas/tests/io/formats/style/test_builtins.py new file mode 100644 index 0000000000000..7753a7ac6a65c --- /dev/null +++ b/pandas/tests/io/formats/style/test_builtins.py @@ -0,0 +1,656 @@ +import numpy as np +import pytest + +import pandas.util._test_decorators as td + +import pandas as pd +from pandas import DataFrame + +jinja2 = pytest.importorskip("jinja2") +from pandas.io.formats.style import Styler + + +def bar_grad(a=None, b=None, c=None, d=None): + """Used in multiple tests to simplify formatting of expected result""" + ret = [("width", "10em"), ("height", "80%")] + if all(x is None for x in [a, b, c, d]): + return ret + return ret + [ + ( + "background", + f"linear-gradient(90deg,{','.join(x for x in [a, b, c, d] if x)})", + ) + ] + + +class TestStyler: + def test_bar_align_left(self): + df = DataFrame({"A": [0, 1, 2]}) + result = df.style.bar()._compute().ctx + expected = { + (0, 0): bar_grad(), + (1, 0): bar_grad("#d65f5f 50.0%", " transparent 50.0%"), + (2, 0): bar_grad("#d65f5f 100.0%", " transparent 100.0%"), + } + assert result == expected + + result = df.style.bar(color="red", width=50)._compute().ctx + expected = { + (0, 0): bar_grad(), + (1, 0): bar_grad("red 25.0%", " transparent 25.0%"), + (2, 0): bar_grad("red 50.0%", " transparent 50.0%"), + } + assert result == expected + + df["C"] = ["a"] * len(df) + result = df.style.bar(color="red", width=50)._compute().ctx + assert result == expected + df["C"] = df["C"].astype("category") + result = df.style.bar(color="red", width=50)._compute().ctx + assert result == expected + + def test_bar_align_left_0points(self): + df = DataFrame([[1, 2, 3], [4, 5, 6], [7, 8, 9]]) + result = df.style.bar()._compute().ctx + expected = { + (0, 0): bar_grad(), + (0, 1): bar_grad(), + (0, 2): bar_grad(), + (1, 0): bar_grad("#d65f5f 50.0%", " transparent 50.0%"), + (1, 1): bar_grad("#d65f5f 50.0%", " transparent 50.0%"), + (1, 2): bar_grad("#d65f5f 50.0%", " transparent 50.0%"), + (2, 0): bar_grad("#d65f5f 100.0%", " transparent 100.0%"), + (2, 1): bar_grad("#d65f5f 100.0%", " transparent 100.0%"), + (2, 2): bar_grad("#d65f5f 100.0%", " transparent 100.0%"), + } + assert result == expected + + result = df.style.bar(axis=1)._compute().ctx + expected = { + (0, 0): bar_grad(), + (0, 1): bar_grad("#d65f5f 50.0%", " transparent 50.0%"), + (0, 2): bar_grad("#d65f5f 100.0%", " transparent 100.0%"), + (1, 0): bar_grad(), + (1, 1): bar_grad("#d65f5f 50.0%", " transparent 50.0%"), + (1, 2): bar_grad("#d65f5f 100.0%", " transparent 100.0%"), + (2, 0): bar_grad(), + (2, 1): bar_grad("#d65f5f 50.0%", " transparent 50.0%"), + (2, 2): bar_grad("#d65f5f 100.0%", " transparent 100.0%"), + } + assert result == expected + + def test_bar_align_mid_pos_and_neg(self): + df = DataFrame({"A": [-10, 0, 20, 90]}) + result = df.style.bar(align="mid", color=["#d65f5f", "#5fba7d"])._compute().ctx + expected = { + (0, 0): bar_grad( + "#d65f5f 10.0%", + " transparent 10.0%", + ), + (1, 0): bar_grad(), + (2, 0): bar_grad( + " transparent 10.0%", + " #5fba7d 10.0%", + " #5fba7d 30.0%", + " transparent 30.0%", + ), + (3, 0): bar_grad( + " transparent 10.0%", + " #5fba7d 10.0%", + " #5fba7d 100.0%", + " transparent 100.0%", + ), + } + assert result == expected + + def test_bar_align_mid_all_pos(self): + df = DataFrame({"A": [10, 20, 50, 100]}) + + result = df.style.bar(align="mid", color=["#d65f5f", "#5fba7d"])._compute().ctx + + expected = { + (0, 0): bar_grad( + "#5fba7d 10.0%", + " transparent 10.0%", + ), + (1, 0): bar_grad( + "#5fba7d 20.0%", + " transparent 20.0%", + ), + (2, 0): bar_grad( + "#5fba7d 50.0%", + " transparent 50.0%", + ), + (3, 0): bar_grad( + "#5fba7d 100.0%", + " transparent 100.0%", + ), + } + + assert result == expected + + def test_bar_align_mid_all_neg(self): + df = DataFrame({"A": [-100, -60, -30, -20]}) + + result = df.style.bar(align="mid", color=["#d65f5f", "#5fba7d"])._compute().ctx + + expected = { + (0, 0): bar_grad( + "#d65f5f 100.0%", + " transparent 100.0%", + ), + (1, 0): bar_grad( + " transparent 40.0%", + " #d65f5f 40.0%", + " #d65f5f 100.0%", + " transparent 100.0%", + ), + (2, 0): bar_grad( + " transparent 70.0%", + " #d65f5f 70.0%", + " #d65f5f 100.0%", + " transparent 100.0%", + ), + (3, 0): bar_grad( + " transparent 80.0%", + " #d65f5f 80.0%", + " #d65f5f 100.0%", + " transparent 100.0%", + ), + } + assert result == expected + + def test_bar_align_zero_pos_and_neg(self): + # See https://github.com/pandas-dev/pandas/pull/14757 + df = DataFrame({"A": [-10, 0, 20, 90]}) + + result = ( + df.style.bar(align="zero", color=["#d65f5f", "#5fba7d"], width=90) + ._compute() + .ctx + ) + expected = { + (0, 0): bar_grad( + " transparent 40.0%", + " #d65f5f 40.0%", + " #d65f5f 45.0%", + " transparent 45.0%", + ), + (1, 0): bar_grad(), + (2, 0): bar_grad( + " transparent 45.0%", + " #5fba7d 45.0%", + " #5fba7d 55.0%", + " transparent 55.0%", + ), + (3, 0): bar_grad( + " transparent 45.0%", + " #5fba7d 45.0%", + " #5fba7d 90.0%", + " transparent 90.0%", + ), + } + assert result == expected + + def test_bar_align_left_axis_none(self): + df = DataFrame({"A": [0, 1], "B": [2, 4]}) + result = df.style.bar(axis=None)._compute().ctx + expected = { + (0, 0): bar_grad(), + (1, 0): bar_grad( + "#d65f5f 25.0%", + " transparent 25.0%", + ), + (0, 1): bar_grad( + "#d65f5f 50.0%", + " transparent 50.0%", + ), + (1, 1): bar_grad( + "#d65f5f 100.0%", + " transparent 100.0%", + ), + } + assert result == expected + + def test_bar_align_zero_axis_none(self): + df = DataFrame({"A": [0, 1], "B": [-2, 4]}) + result = df.style.bar(align="zero", axis=None)._compute().ctx + expected = { + (0, 0): bar_grad(), + (1, 0): bar_grad( + " transparent 50.0%", + " #d65f5f 50.0%", + " #d65f5f 62.5%", + " transparent 62.5%", + ), + (0, 1): bar_grad( + " transparent 25.0%", + " #d65f5f 25.0%", + " #d65f5f 50.0%", + " transparent 50.0%", + ), + (1, 1): bar_grad( + " transparent 50.0%", + " #d65f5f 50.0%", + " #d65f5f 100.0%", + " transparent 100.0%", + ), + } + assert result == expected + + def test_bar_align_mid_axis_none(self): + df = DataFrame({"A": [0, 1], "B": [-2, 4]}) + result = df.style.bar(align="mid", axis=None)._compute().ctx + expected = { + (0, 0): bar_grad(), + (1, 0): bar_grad( + " transparent 33.3%", + " #d65f5f 33.3%", + " #d65f5f 50.0%", + " transparent 50.0%", + ), + (0, 1): bar_grad( + "#d65f5f 33.3%", + " transparent 33.3%", + ), + (1, 1): bar_grad( + " transparent 33.3%", + " #d65f5f 33.3%", + " #d65f5f 100.0%", + " transparent 100.0%", + ), + } + assert result == expected + + def test_bar_align_mid_vmin(self): + df = DataFrame({"A": [0, 1], "B": [-2, 4]}) + result = df.style.bar(align="mid", axis=None, vmin=-6)._compute().ctx + expected = { + (0, 0): bar_grad(), + (1, 0): bar_grad( + " transparent 60.0%", + " #d65f5f 60.0%", + " #d65f5f 70.0%", + " transparent 70.0%", + ), + (0, 1): bar_grad( + " transparent 40.0%", + " #d65f5f 40.0%", + " #d65f5f 60.0%", + " transparent 60.0%", + ), + (1, 1): bar_grad( + " transparent 60.0%", + " #d65f5f 60.0%", + " #d65f5f 100.0%", + " transparent 100.0%", + ), + } + assert result == expected + + def test_bar_align_mid_vmax(self): + df = DataFrame({"A": [0, 1], "B": [-2, 4]}) + result = df.style.bar(align="mid", axis=None, vmax=8)._compute().ctx + expected = { + (0, 0): bar_grad(), + (1, 0): bar_grad( + " transparent 20.0%", + " #d65f5f 20.0%", + " #d65f5f 30.0%", + " transparent 30.0%", + ), + (0, 1): bar_grad( + "#d65f5f 20.0%", + " transparent 20.0%", + ), + (1, 1): bar_grad( + " transparent 20.0%", + " #d65f5f 20.0%", + " #d65f5f 60.0%", + " transparent 60.0%", + ), + } + assert result == expected + + def test_bar_align_mid_vmin_vmax_wide(self): + df = DataFrame({"A": [0, 1], "B": [-2, 4]}) + result = df.style.bar(align="mid", axis=None, vmin=-3, vmax=7)._compute().ctx + expected = { + (0, 0): bar_grad(), + (1, 0): bar_grad( + " transparent 30.0%", + " #d65f5f 30.0%", + " #d65f5f 40.0%", + " transparent 40.0%", + ), + (0, 1): bar_grad( + " transparent 10.0%", + " #d65f5f 10.0%", + " #d65f5f 30.0%", + " transparent 30.0%", + ), + (1, 1): bar_grad( + " transparent 30.0%", + " #d65f5f 30.0%", + " #d65f5f 70.0%", + " transparent 70.0%", + ), + } + assert result == expected + + def test_bar_align_mid_vmin_vmax_clipping(self): + df = DataFrame({"A": [0, 1], "B": [-2, 4]}) + result = df.style.bar(align="mid", axis=None, vmin=-1, vmax=3)._compute().ctx + expected = { + (0, 0): bar_grad(), + (1, 0): bar_grad( + " transparent 25.0%", + " #d65f5f 25.0%", + " #d65f5f 50.0%", + " transparent 50.0%", + ), + (0, 1): bar_grad("#d65f5f 25.0%", " transparent 25.0%"), + (1, 1): bar_grad( + " transparent 25.0%", + " #d65f5f 25.0%", + " #d65f5f 100.0%", + " transparent 100.0%", + ), + } + assert result == expected + + def test_bar_align_mid_nans(self): + df = DataFrame({"A": [1, None], "B": [-1, 3]}) + result = df.style.bar(align="mid", axis=None)._compute().ctx + expected = { + (0, 0): bar_grad( + " transparent 25.0%", + " #d65f5f 25.0%", + " #d65f5f 50.0%", + " transparent 50.0%", + ), + (0, 1): bar_grad("#d65f5f 25.0%", " transparent 25.0%"), + (1, 1): bar_grad( + " transparent 25.0%", + " #d65f5f 25.0%", + " #d65f5f 100.0%", + " transparent 100.0%", + ), + } + assert result == expected + + def test_bar_align_zero_nans(self): + df = DataFrame({"A": [1, None], "B": [-1, 2]}) + result = df.style.bar(align="zero", axis=None)._compute().ctx + expected = { + (0, 0): bar_grad( + " transparent 50.0%", + " #d65f5f 50.0%", + " #d65f5f 75.0%", + " transparent 75.0%", + ), + (0, 1): bar_grad( + " transparent 25.0%", + " #d65f5f 25.0%", + " #d65f5f 50.0%", + " transparent 50.0%", + ), + (1, 1): bar_grad( + " transparent 50.0%", + " #d65f5f 50.0%", + " #d65f5f 100.0%", + " transparent 100.0%", + ), + } + assert result == expected + + def test_bar_bad_align_raises(self): + df = DataFrame({"A": [-100, -60, -30, -20]}) + msg = "`align` must be one of {'left', 'zero',' mid'}" + with pytest.raises(ValueError, match=msg): + df.style.bar(align="poorly", color=["#d65f5f", "#5fba7d"]) + + def test_highlight_null(self): + df = DataFrame({"A": [0, np.nan]}) + result = df.style.highlight_null()._compute().ctx + expected = {(1, 0): [("background-color", "red")]} + assert result == expected + + def test_highlight_null_subset(self): + # GH 31345 + df = DataFrame({"A": [0, np.nan], "B": [0, np.nan]}) + result = ( + df.style.highlight_null(null_color="red", subset=["A"]) + .highlight_null(null_color="green", subset=["B"]) + ._compute() + .ctx + ) + expected = { + (1, 0): [("background-color", "red")], + (1, 1): [("background-color", "green")], + } + assert result == expected + + def test_highlight_max(self): + df = DataFrame([[1, 2], [3, 4]], columns=["A", "B"]) + css_seq = [("background-color", "yellow")] + # max(df) = min(-df) + for max_ in [True, False]: + if max_: + attr = "highlight_max" + else: + df = -df + attr = "highlight_min" + result = getattr(df.style, attr)()._compute().ctx + assert result[(1, 1)] == css_seq + + result = getattr(df.style, attr)(color="green")._compute().ctx + assert result[(1, 1)] == [("background-color", "green")] + + result = getattr(df.style, attr)(subset="A")._compute().ctx + assert result[(1, 0)] == css_seq + + result = getattr(df.style, attr)(axis=0)._compute().ctx + expected = { + (1, 0): css_seq, + (1, 1): css_seq, + } + assert result == expected + + result = getattr(df.style, attr)(axis=1)._compute().ctx + expected = { + (0, 1): css_seq, + (1, 1): css_seq, + } + assert result == expected + + # separate since we can't negate the strs + df["C"] = ["a", "b"] + result = df.style.highlight_max()._compute().ctx + expected = {(1, 1): css_seq} + + result = df.style.highlight_min()._compute().ctx + expected = {(0, 0): css_seq} + + @pytest.mark.parametrize( + "ttips", + [ + DataFrame( + data=[["Min", "Max"], [np.nan, ""]], + columns=["A", "B"], + index=["a", "b"], + ), + DataFrame(data=[["Max", "Min"]], columns=["B", "A"], index=["a"]), + DataFrame( + data=[["Min", "Max", None]], columns=["A", "B", "C"], index=["a"] + ), + ], + ) + def test_tooltip_render(self, ttips): + # GH 21266 + df = DataFrame(data=[[0, 3], [1, 2]], columns=["A", "B"], index=["a", "b"]) + s = Styler(df, uuid_len=0).set_tooltips(ttips).render() + + # test tooltip table level class + assert "#T__ .pd-t {\n visibility: hidden;\n" in s + + # test 'Min' tooltip added + assert ( + "#T__ #T__row0_col0:hover .pd-t {\n visibility: visible;\n}\n" + + '#T__ #T__row0_col0 .pd-t::after {\n content: "Min";\n}' + in s + ) + assert ( + '0' + + "" + in s + ) + + # test 'Max' tooltip added + assert ( + "#T__ #T__row0_col1:hover .pd-t {\n visibility: visible;\n}\n" + + '#T__ #T__row0_col1 .pd-t::after {\n content: "Max";\n}' + in s + ) + assert ( + '3' + + "" + in s + ) + + def test_tooltip_reindex(self): + # GH 39317 + df = DataFrame( + data=[[0, 1, 2], [3, 4, 5], [6, 7, 8]], columns=[0, 1, 2], index=[0, 1, 2] + ) + ttips = DataFrame( + data=[["Mi", "Ma"], ["Mu", "Mo"]], + columns=[0, 2], + index=[0, 2], + ) + s = Styler(df, uuid_len=0).set_tooltips(DataFrame(ttips)).render() + assert '#T__ #T__row0_col0 .pd-t::after {\n content: "Mi";\n}' in s + assert '#T__ #T__row0_col2 .pd-t::after {\n content: "Ma";\n}' in s + assert '#T__ #T__row2_col0 .pd-t::after {\n content: "Mu";\n}' in s + assert '#T__ #T__row2_col2 .pd-t::after {\n content: "Mo";\n}' in s + + def test_tooltip_ignored(self): + # GH 21266 + df = DataFrame(data=[[0, 1], [2, 3]]) + s = Styler(df).set_tooltips_class("pd-t").render() # no set_tooltips() + assert '' in s + assert '' not in s + + def test_tooltip_class(self): + # GH 21266 + df = DataFrame(data=[[0, 1], [2, 3]]) + s = ( + Styler(df, uuid_len=0) + .set_tooltips(DataFrame([["tooltip"]])) + .set_tooltips_class(name="other-class", properties=[("color", "green")]) + .render() + ) + assert "#T__ .other-class {\n color: green;\n" in s + assert '#T__ #T__row0_col0 .other-class::after {\n content: "tooltip";\n' in s + + # GH 39563 + s = ( + Styler(df, uuid_len=0) + .set_tooltips(DataFrame([["tooltip"]])) + .set_tooltips_class(name="other-class", properties="color:green;color:red;") + .render() + ) + assert "#T__ .other-class {\n color: green;\n color: red;\n}" in s + + +@td.skip_if_no_mpl +class TestStylerMatplotlibDep: + def test_background_gradient(self): + df = DataFrame([[1, 2], [2, 4]], columns=["A", "B"]) + + for c_map in [None, "YlOrRd"]: + result = df.style.background_gradient(cmap=c_map)._compute().ctx + assert all("#" in x[0][1] for x in result.values()) + assert result[(0, 0)] == result[(0, 1)] + assert result[(1, 0)] == result[(1, 1)] + + result = ( + df.style.background_gradient(subset=pd.IndexSlice[1, "A"])._compute().ctx + ) + + assert result[(1, 0)] == [("background-color", "#fff7fb"), ("color", "#000000")] + + @pytest.mark.parametrize( + "c_map,expected", + [ + ( + None, + { + (0, 0): [("background-color", "#440154"), ("color", "#f1f1f1")], + (1, 0): [("background-color", "#fde725"), ("color", "#000000")], + }, + ), + ( + "YlOrRd", + { + (0, 0): [("background-color", "#ffffcc"), ("color", "#000000")], + (1, 0): [("background-color", "#800026"), ("color", "#f1f1f1")], + }, + ), + ], + ) + def test_text_color_threshold(self, c_map, expected): + df = DataFrame([1, 2], columns=["A"]) + result = df.style.background_gradient(cmap=c_map)._compute().ctx + assert result == expected + + @pytest.mark.parametrize("text_color_threshold", [1.1, "1", -1, [2, 2]]) + def test_text_color_threshold_raises(self, text_color_threshold): + df = DataFrame([[1, 2], [2, 4]], columns=["A", "B"]) + msg = "`text_color_threshold` must be a value from 0 to 1." + with pytest.raises(ValueError, match=msg): + df.style.background_gradient( + text_color_threshold=text_color_threshold + )._compute() + + @td.skip_if_no_mpl + def test_background_gradient_axis(self): + df = DataFrame([[1, 2], [2, 4]], columns=["A", "B"]) + + low = [("background-color", "#f7fbff"), ("color", "#000000")] + high = [("background-color", "#08306b"), ("color", "#f1f1f1")] + mid = [("background-color", "#abd0e6"), ("color", "#000000")] + result = df.style.background_gradient(cmap="Blues", axis=0)._compute().ctx + assert result[(0, 0)] == low + assert result[(0, 1)] == low + assert result[(1, 0)] == high + assert result[(1, 1)] == high + + result = df.style.background_gradient(cmap="Blues", axis=1)._compute().ctx + assert result[(0, 0)] == low + assert result[(0, 1)] == high + assert result[(1, 0)] == low + assert result[(1, 1)] == high + + result = df.style.background_gradient(cmap="Blues", axis=None)._compute().ctx + assert result[(0, 0)] == low + assert result[(0, 1)] == mid + assert result[(1, 0)] == mid + assert result[(1, 1)] == high + + def test_background_gradient_vmin_vmax(self): + # GH 12145 + df = DataFrame(range(5)) + ctx = df.style.background_gradient(vmin=1, vmax=3)._compute().ctx + assert ctx[(0, 0)] == ctx[(1, 0)] + assert ctx[(4, 0)] == ctx[(3, 0)] + + def test_background_gradient_int64(self): + # GH 28869 + df1 = pd.Series(range(3)).to_frame() + df2 = pd.Series(range(3), dtype="Int64").to_frame() + ctx1 = df1.style.background_gradient()._compute().ctx + ctx2 = df2.style.background_gradient()._compute().ctx + assert ctx2[(0, 0)] == ctx1[(0, 0)] + assert ctx2[(1, 0)] == ctx1[(1, 0)] + assert ctx2[(2, 0)] == ctx1[(2, 0)] diff --git a/pandas/tests/io/formats/test_style.py b/pandas/tests/io/formats/style/test_style.py similarity index 69% rename from pandas/tests/io/formats/test_style.py rename to pandas/tests/io/formats/style/test_style.py index d134f33e15525..a10bf92a00565 100644 --- a/pandas/tests/io/formats/test_style.py +++ b/pandas/tests/io/formats/style/test_style.py @@ -5,8 +5,6 @@ import numpy as np import pytest -import pandas.util._test_decorators as td - import pandas as pd from pandas import DataFrame import pandas._testing as tm @@ -20,19 +18,6 @@ ) -def bar_grad(a=None, b=None, c=None, d=None): - """Used in multiple tests to simplify formatting of expected result""" - ret = [("width", "10em"), ("height", "80%")] - if all(x is None for x in [a, b, c, d]): - return ret - return ret + [ - ( - "background", - f"linear-gradient(90deg,{','.join(x for x in [a, b, c, d] if x)})", - ) - ] - - class TestStyler: def setup_method(self, method): np.random.seed(24) @@ -517,392 +502,6 @@ def test_duplicate(self): ] assert result == expected - def test_bar_align_left(self): - df = DataFrame({"A": [0, 1, 2]}) - result = df.style.bar()._compute().ctx - expected = { - (0, 0): bar_grad(), - (1, 0): bar_grad("#d65f5f 50.0%", " transparent 50.0%"), - (2, 0): bar_grad("#d65f5f 100.0%", " transparent 100.0%"), - } - assert result == expected - - result = df.style.bar(color="red", width=50)._compute().ctx - expected = { - (0, 0): bar_grad(), - (1, 0): bar_grad("red 25.0%", " transparent 25.0%"), - (2, 0): bar_grad("red 50.0%", " transparent 50.0%"), - } - assert result == expected - - df["C"] = ["a"] * len(df) - result = df.style.bar(color="red", width=50)._compute().ctx - assert result == expected - df["C"] = df["C"].astype("category") - result = df.style.bar(color="red", width=50)._compute().ctx - assert result == expected - - def test_bar_align_left_0points(self): - df = DataFrame([[1, 2, 3], [4, 5, 6], [7, 8, 9]]) - result = df.style.bar()._compute().ctx - expected = { - (0, 0): bar_grad(), - (0, 1): bar_grad(), - (0, 2): bar_grad(), - (1, 0): bar_grad("#d65f5f 50.0%", " transparent 50.0%"), - (1, 1): bar_grad("#d65f5f 50.0%", " transparent 50.0%"), - (1, 2): bar_grad("#d65f5f 50.0%", " transparent 50.0%"), - (2, 0): bar_grad("#d65f5f 100.0%", " transparent 100.0%"), - (2, 1): bar_grad("#d65f5f 100.0%", " transparent 100.0%"), - (2, 2): bar_grad("#d65f5f 100.0%", " transparent 100.0%"), - } - assert result == expected - - result = df.style.bar(axis=1)._compute().ctx - expected = { - (0, 0): bar_grad(), - (0, 1): bar_grad("#d65f5f 50.0%", " transparent 50.0%"), - (0, 2): bar_grad("#d65f5f 100.0%", " transparent 100.0%"), - (1, 0): bar_grad(), - (1, 1): bar_grad("#d65f5f 50.0%", " transparent 50.0%"), - (1, 2): bar_grad("#d65f5f 100.0%", " transparent 100.0%"), - (2, 0): bar_grad(), - (2, 1): bar_grad("#d65f5f 50.0%", " transparent 50.0%"), - (2, 2): bar_grad("#d65f5f 100.0%", " transparent 100.0%"), - } - assert result == expected - - def test_bar_align_mid_pos_and_neg(self): - df = DataFrame({"A": [-10, 0, 20, 90]}) - result = df.style.bar(align="mid", color=["#d65f5f", "#5fba7d"])._compute().ctx - expected = { - (0, 0): bar_grad( - "#d65f5f 10.0%", - " transparent 10.0%", - ), - (1, 0): bar_grad(), - (2, 0): bar_grad( - " transparent 10.0%", - " #5fba7d 10.0%", - " #5fba7d 30.0%", - " transparent 30.0%", - ), - (3, 0): bar_grad( - " transparent 10.0%", - " #5fba7d 10.0%", - " #5fba7d 100.0%", - " transparent 100.0%", - ), - } - assert result == expected - - def test_bar_align_mid_all_pos(self): - df = DataFrame({"A": [10, 20, 50, 100]}) - - result = df.style.bar(align="mid", color=["#d65f5f", "#5fba7d"])._compute().ctx - - expected = { - (0, 0): bar_grad( - "#5fba7d 10.0%", - " transparent 10.0%", - ), - (1, 0): bar_grad( - "#5fba7d 20.0%", - " transparent 20.0%", - ), - (2, 0): bar_grad( - "#5fba7d 50.0%", - " transparent 50.0%", - ), - (3, 0): bar_grad( - "#5fba7d 100.0%", - " transparent 100.0%", - ), - } - - assert result == expected - - def test_bar_align_mid_all_neg(self): - df = DataFrame({"A": [-100, -60, -30, -20]}) - - result = df.style.bar(align="mid", color=["#d65f5f", "#5fba7d"])._compute().ctx - - expected = { - (0, 0): bar_grad( - "#d65f5f 100.0%", - " transparent 100.0%", - ), - (1, 0): bar_grad( - " transparent 40.0%", - " #d65f5f 40.0%", - " #d65f5f 100.0%", - " transparent 100.0%", - ), - (2, 0): bar_grad( - " transparent 70.0%", - " #d65f5f 70.0%", - " #d65f5f 100.0%", - " transparent 100.0%", - ), - (3, 0): bar_grad( - " transparent 80.0%", - " #d65f5f 80.0%", - " #d65f5f 100.0%", - " transparent 100.0%", - ), - } - assert result == expected - - def test_bar_align_zero_pos_and_neg(self): - # See https://github.com/pandas-dev/pandas/pull/14757 - df = DataFrame({"A": [-10, 0, 20, 90]}) - - result = ( - df.style.bar(align="zero", color=["#d65f5f", "#5fba7d"], width=90) - ._compute() - .ctx - ) - expected = { - (0, 0): bar_grad( - " transparent 40.0%", - " #d65f5f 40.0%", - " #d65f5f 45.0%", - " transparent 45.0%", - ), - (1, 0): bar_grad(), - (2, 0): bar_grad( - " transparent 45.0%", - " #5fba7d 45.0%", - " #5fba7d 55.0%", - " transparent 55.0%", - ), - (3, 0): bar_grad( - " transparent 45.0%", - " #5fba7d 45.0%", - " #5fba7d 90.0%", - " transparent 90.0%", - ), - } - assert result == expected - - def test_bar_align_left_axis_none(self): - df = DataFrame({"A": [0, 1], "B": [2, 4]}) - result = df.style.bar(axis=None)._compute().ctx - expected = { - (0, 0): bar_grad(), - (1, 0): bar_grad( - "#d65f5f 25.0%", - " transparent 25.0%", - ), - (0, 1): bar_grad( - "#d65f5f 50.0%", - " transparent 50.0%", - ), - (1, 1): bar_grad( - "#d65f5f 100.0%", - " transparent 100.0%", - ), - } - assert result == expected - - def test_bar_align_zero_axis_none(self): - df = DataFrame({"A": [0, 1], "B": [-2, 4]}) - result = df.style.bar(align="zero", axis=None)._compute().ctx - expected = { - (0, 0): bar_grad(), - (1, 0): bar_grad( - " transparent 50.0%", - " #d65f5f 50.0%", - " #d65f5f 62.5%", - " transparent 62.5%", - ), - (0, 1): bar_grad( - " transparent 25.0%", - " #d65f5f 25.0%", - " #d65f5f 50.0%", - " transparent 50.0%", - ), - (1, 1): bar_grad( - " transparent 50.0%", - " #d65f5f 50.0%", - " #d65f5f 100.0%", - " transparent 100.0%", - ), - } - assert result == expected - - def test_bar_align_mid_axis_none(self): - df = DataFrame({"A": [0, 1], "B": [-2, 4]}) - result = df.style.bar(align="mid", axis=None)._compute().ctx - expected = { - (0, 0): bar_grad(), - (1, 0): bar_grad( - " transparent 33.3%", - " #d65f5f 33.3%", - " #d65f5f 50.0%", - " transparent 50.0%", - ), - (0, 1): bar_grad( - "#d65f5f 33.3%", - " transparent 33.3%", - ), - (1, 1): bar_grad( - " transparent 33.3%", - " #d65f5f 33.3%", - " #d65f5f 100.0%", - " transparent 100.0%", - ), - } - assert result == expected - - def test_bar_align_mid_vmin(self): - df = DataFrame({"A": [0, 1], "B": [-2, 4]}) - result = df.style.bar(align="mid", axis=None, vmin=-6)._compute().ctx - expected = { - (0, 0): bar_grad(), - (1, 0): bar_grad( - " transparent 60.0%", - " #d65f5f 60.0%", - " #d65f5f 70.0%", - " transparent 70.0%", - ), - (0, 1): bar_grad( - " transparent 40.0%", - " #d65f5f 40.0%", - " #d65f5f 60.0%", - " transparent 60.0%", - ), - (1, 1): bar_grad( - " transparent 60.0%", - " #d65f5f 60.0%", - " #d65f5f 100.0%", - " transparent 100.0%", - ), - } - assert result == expected - - def test_bar_align_mid_vmax(self): - df = DataFrame({"A": [0, 1], "B": [-2, 4]}) - result = df.style.bar(align="mid", axis=None, vmax=8)._compute().ctx - expected = { - (0, 0): bar_grad(), - (1, 0): bar_grad( - " transparent 20.0%", - " #d65f5f 20.0%", - " #d65f5f 30.0%", - " transparent 30.0%", - ), - (0, 1): bar_grad( - "#d65f5f 20.0%", - " transparent 20.0%", - ), - (1, 1): bar_grad( - " transparent 20.0%", - " #d65f5f 20.0%", - " #d65f5f 60.0%", - " transparent 60.0%", - ), - } - assert result == expected - - def test_bar_align_mid_vmin_vmax_wide(self): - df = DataFrame({"A": [0, 1], "B": [-2, 4]}) - result = df.style.bar(align="mid", axis=None, vmin=-3, vmax=7)._compute().ctx - expected = { - (0, 0): bar_grad(), - (1, 0): bar_grad( - " transparent 30.0%", - " #d65f5f 30.0%", - " #d65f5f 40.0%", - " transparent 40.0%", - ), - (0, 1): bar_grad( - " transparent 10.0%", - " #d65f5f 10.0%", - " #d65f5f 30.0%", - " transparent 30.0%", - ), - (1, 1): bar_grad( - " transparent 30.0%", - " #d65f5f 30.0%", - " #d65f5f 70.0%", - " transparent 70.0%", - ), - } - assert result == expected - - def test_bar_align_mid_vmin_vmax_clipping(self): - df = DataFrame({"A": [0, 1], "B": [-2, 4]}) - result = df.style.bar(align="mid", axis=None, vmin=-1, vmax=3)._compute().ctx - expected = { - (0, 0): bar_grad(), - (1, 0): bar_grad( - " transparent 25.0%", - " #d65f5f 25.0%", - " #d65f5f 50.0%", - " transparent 50.0%", - ), - (0, 1): bar_grad("#d65f5f 25.0%", " transparent 25.0%"), - (1, 1): bar_grad( - " transparent 25.0%", - " #d65f5f 25.0%", - " #d65f5f 100.0%", - " transparent 100.0%", - ), - } - assert result == expected - - def test_bar_align_mid_nans(self): - df = DataFrame({"A": [1, None], "B": [-1, 3]}) - result = df.style.bar(align="mid", axis=None)._compute().ctx - expected = { - (0, 0): bar_grad( - " transparent 25.0%", - " #d65f5f 25.0%", - " #d65f5f 50.0%", - " transparent 50.0%", - ), - (0, 1): bar_grad("#d65f5f 25.0%", " transparent 25.0%"), - (1, 1): bar_grad( - " transparent 25.0%", - " #d65f5f 25.0%", - " #d65f5f 100.0%", - " transparent 100.0%", - ), - } - assert result == expected - - def test_bar_align_zero_nans(self): - df = DataFrame({"A": [1, None], "B": [-1, 2]}) - result = df.style.bar(align="zero", axis=None)._compute().ctx - expected = { - (0, 0): bar_grad( - " transparent 50.0%", - " #d65f5f 50.0%", - " #d65f5f 75.0%", - " transparent 75.0%", - ), - (0, 1): bar_grad( - " transparent 25.0%", - " #d65f5f 25.0%", - " #d65f5f 50.0%", - " transparent 50.0%", - ), - (1, 1): bar_grad( - " transparent 50.0%", - " #d65f5f 50.0%", - " #d65f5f 100.0%", - " transparent 100.0%", - ), - } - assert result == expected - - def test_bar_bad_align_raises(self): - df = DataFrame({"A": [-100, -60, -30, -20]}) - msg = "`align` must be one of {'left', 'zero',' mid'}" - with pytest.raises(ValueError, match=msg): - df.style.bar(align="poorly", color=["#d65f5f", "#5fba7d"]) - def test_format_with_na_rep(self): # GH 21527 28358 df = DataFrame([[None, None], [1.1, 1.2]], columns=["A", "B"]) @@ -973,27 +572,6 @@ def test_format_with_bad_na_rep(self): with pytest.raises(TypeError, match=msg): df.style.format(None, na_rep=-1) - def test_highlight_null(self, null_color="red"): - df = DataFrame({"A": [0, np.nan]}) - result = df.style.highlight_null()._compute().ctx - expected = {(1, 0): [("background-color", "red")]} - assert result == expected - - def test_highlight_null_subset(self): - # GH 31345 - df = DataFrame({"A": [0, np.nan], "B": [0, np.nan]}) - result = ( - df.style.highlight_null(null_color="red", subset=["A"]) - .highlight_null(null_color="green", subset=["B"]) - ._compute() - .ctx - ) - expected = { - (1, 0): [("background-color", "red")], - (1, 1): [("background-color", "green")], - } - assert result == expected - def test_nonunique_raises(self): df = DataFrame([[1, 2]], columns=["A", "A"]) msg = "style is not supported for non-unique indices." @@ -1098,47 +676,6 @@ def test_trim(self): result = self.df.style.highlight_max().render() assert result.count("#") == len(self.df.columns) - def test_highlight_max(self): - df = DataFrame([[1, 2], [3, 4]], columns=["A", "B"]) - css_seq = [("background-color", "yellow")] - # max(df) = min(-df) - for max_ in [True, False]: - if max_: - attr = "highlight_max" - else: - df = -df - attr = "highlight_min" - result = getattr(df.style, attr)()._compute().ctx - assert result[(1, 1)] == css_seq - - result = getattr(df.style, attr)(color="green")._compute().ctx - assert result[(1, 1)] == [("background-color", "green")] - - result = getattr(df.style, attr)(subset="A")._compute().ctx - assert result[(1, 0)] == css_seq - - result = getattr(df.style, attr)(axis=0)._compute().ctx - expected = { - (1, 0): css_seq, - (1, 1): css_seq, - } - assert result == expected - - result = getattr(df.style, attr)(axis=1)._compute().ctx - expected = { - (0, 1): css_seq, - (1, 1): css_seq, - } - assert result == expected - - # separate since we can't negate the strs - df["C"] = ["a", "b"] - result = df.style.highlight_max()._compute().ctx - expected = {(1, 1): css_seq} - - result = df.style.highlight_min()._compute().ctx - expected = {(0, 0): css_seq} - def test_export(self): f = lambda x: "color: red" if x > 0 else "color: blue" g = lambda x, z: f"color: {z}" if x > 0 else f"color: {z}" @@ -1704,96 +1241,6 @@ def test_uuid_len_raises(self, len_): with pytest.raises(TypeError, match=msg): Styler(df, uuid_len=len_, cell_ids=False).render() - @pytest.mark.parametrize( - "ttips", - [ - DataFrame( - data=[["Min", "Max"], [np.nan, ""]], - columns=["A", "B"], - index=["a", "b"], - ), - DataFrame(data=[["Max", "Min"]], columns=["B", "A"], index=["a"]), - DataFrame( - data=[["Min", "Max", None]], columns=["A", "B", "C"], index=["a"] - ), - ], - ) - def test_tooltip_render(self, ttips): - # GH 21266 - df = DataFrame(data=[[0, 3], [1, 2]], columns=["A", "B"], index=["a", "b"]) - s = Styler(df, uuid_len=0).set_tooltips(ttips).render() - - # test tooltip table level class - assert "#T__ .pd-t {\n visibility: hidden;\n" in s - - # test 'Min' tooltip added - assert ( - "#T__ #T__row0_col0:hover .pd-t {\n visibility: visible;\n}\n" - + '#T__ #T__row0_col0 .pd-t::after {\n content: "Min";\n}' - in s - ) - assert ( - '0' - + "" - in s - ) - - # test 'Max' tooltip added - assert ( - "#T__ #T__row0_col1:hover .pd-t {\n visibility: visible;\n}\n" - + '#T__ #T__row0_col1 .pd-t::after {\n content: "Max";\n}' - in s - ) - assert ( - '3' - + "" - in s - ) - - def test_tooltip_reindex(self): - # GH 39317 - df = DataFrame( - data=[[0, 1, 2], [3, 4, 5], [6, 7, 8]], columns=[0, 1, 2], index=[0, 1, 2] - ) - ttips = DataFrame( - data=[["Mi", "Ma"], ["Mu", "Mo"]], - columns=[0, 2], - index=[0, 2], - ) - s = Styler(df, uuid_len=0).set_tooltips(DataFrame(ttips)).render() - assert '#T__ #T__row0_col0 .pd-t::after {\n content: "Mi";\n}' in s - assert '#T__ #T__row0_col2 .pd-t::after {\n content: "Ma";\n}' in s - assert '#T__ #T__row2_col0 .pd-t::after {\n content: "Mu";\n}' in s - assert '#T__ #T__row2_col2 .pd-t::after {\n content: "Mo";\n}' in s - - def test_tooltip_ignored(self): - # GH 21266 - df = DataFrame(data=[[0, 1], [2, 3]]) - s = Styler(df).set_tooltips_class("pd-t").render() # no set_tooltips() - assert '' in s - assert '' not in s - - def test_tooltip_class(self): - # GH 21266 - df = DataFrame(data=[[0, 1], [2, 3]]) - s = ( - Styler(df, uuid_len=0) - .set_tooltips(DataFrame([["tooltip"]])) - .set_tooltips_class(name="other-class", properties=[("color", "green")]) - .render() - ) - assert "#T__ .other-class {\n color: green;\n" in s - assert '#T__ #T__row0_col0 .other-class::after {\n content: "tooltip";\n' in s - - # GH 39563 - s = ( - Styler(df, uuid_len=0) - .set_tooltips(DataFrame([["tooltip"]])) - .set_tooltips_class(name="other-class", properties="color:green;color:red;") - .render() - ) - assert "#T__ .other-class {\n color: green;\n color: red;\n}" in s - def test_w3_html_format(self): s = ( Styler( @@ -1925,99 +1372,6 @@ def test_non_reducing_multi_slice_on_multiindex(self, slice_): tm.assert_frame_equal(result, expected) -@td.skip_if_no_mpl -class TestStylerMatplotlibDep: - def test_background_gradient(self): - df = DataFrame([[1, 2], [2, 4]], columns=["A", "B"]) - - for c_map in [None, "YlOrRd"]: - result = df.style.background_gradient(cmap=c_map)._compute().ctx - assert all("#" in x[0][1] for x in result.values()) - assert result[(0, 0)] == result[(0, 1)] - assert result[(1, 0)] == result[(1, 1)] - - result = ( - df.style.background_gradient(subset=pd.IndexSlice[1, "A"])._compute().ctx - ) - - assert result[(1, 0)] == [("background-color", "#fff7fb"), ("color", "#000000")] - - @pytest.mark.parametrize( - "c_map,expected", - [ - ( - None, - { - (0, 0): [("background-color", "#440154"), ("color", "#f1f1f1")], - (1, 0): [("background-color", "#fde725"), ("color", "#000000")], - }, - ), - ( - "YlOrRd", - { - (0, 0): [("background-color", "#ffffcc"), ("color", "#000000")], - (1, 0): [("background-color", "#800026"), ("color", "#f1f1f1")], - }, - ), - ], - ) - def test_text_color_threshold(self, c_map, expected): - df = DataFrame([1, 2], columns=["A"]) - result = df.style.background_gradient(cmap=c_map)._compute().ctx - assert result == expected - - @pytest.mark.parametrize("text_color_threshold", [1.1, "1", -1, [2, 2]]) - def test_text_color_threshold_raises(self, text_color_threshold): - df = DataFrame([[1, 2], [2, 4]], columns=["A", "B"]) - msg = "`text_color_threshold` must be a value from 0 to 1." - with pytest.raises(ValueError, match=msg): - df.style.background_gradient( - text_color_threshold=text_color_threshold - )._compute() - - @td.skip_if_no_mpl - def test_background_gradient_axis(self): - df = DataFrame([[1, 2], [2, 4]], columns=["A", "B"]) - - low = [("background-color", "#f7fbff"), ("color", "#000000")] - high = [("background-color", "#08306b"), ("color", "#f1f1f1")] - mid = [("background-color", "#abd0e6"), ("color", "#000000")] - result = df.style.background_gradient(cmap="Blues", axis=0)._compute().ctx - assert result[(0, 0)] == low - assert result[(0, 1)] == low - assert result[(1, 0)] == high - assert result[(1, 1)] == high - - result = df.style.background_gradient(cmap="Blues", axis=1)._compute().ctx - assert result[(0, 0)] == low - assert result[(0, 1)] == high - assert result[(1, 0)] == low - assert result[(1, 1)] == high - - result = df.style.background_gradient(cmap="Blues", axis=None)._compute().ctx - assert result[(0, 0)] == low - assert result[(0, 1)] == mid - assert result[(1, 0)] == mid - assert result[(1, 1)] == high - - def test_background_gradient_vmin_vmax(self): - # GH 12145 - df = DataFrame(range(5)) - ctx = df.style.background_gradient(vmin=1, vmax=3)._compute().ctx - assert ctx[(0, 0)] == ctx[(1, 0)] - assert ctx[(4, 0)] == ctx[(3, 0)] - - def test_background_gradient_int64(self): - # GH 28869 - df1 = pd.Series(range(3)).to_frame() - df2 = pd.Series(range(3), dtype="Int64").to_frame() - ctx1 = df1.style.background_gradient()._compute().ctx - ctx2 = df2.style.background_gradient()._compute().ctx - assert ctx2[(0, 0)] == ctx1[(0, 0)] - assert ctx2[(1, 0)] == ctx1[(1, 0)] - assert ctx2[(2, 0)] == ctx1[(2, 0)] - - def test_block_names(): # catch accidental removal of a block expected = { From 41fef6109d6182e9a1b470a29b15b781b6e0daf2 Mon Sep 17 00:00:00 2001 From: "JHM Darbyshire (iMac)" Date: Mon, 22 Feb 2021 08:22:29 +0100 Subject: [PATCH 2/7] refactor --- .../style/{test_builtins.py => test_align.py} | 252 +----------------- .../tests/io/formats/style/test_highlight.py | 70 +++++ pandas/tests/io/formats/style/test_tooltip.py | 99 +++++++ pandas/tests/plotting/test_style.py | 99 ++++++- 4 files changed, 268 insertions(+), 252 deletions(-) rename pandas/tests/io/formats/style/{test_builtins.py => test_align.py} (59%) create mode 100644 pandas/tests/io/formats/style/test_highlight.py create mode 100644 pandas/tests/io/formats/style/test_tooltip.py diff --git a/pandas/tests/io/formats/style/test_builtins.py b/pandas/tests/io/formats/style/test_align.py similarity index 59% rename from pandas/tests/io/formats/style/test_builtins.py rename to pandas/tests/io/formats/style/test_align.py index 7753a7ac6a65c..60ebff2231a70 100644 --- a/pandas/tests/io/formats/style/test_builtins.py +++ b/pandas/tests/io/formats/style/test_align.py @@ -1,13 +1,8 @@ -import numpy as np import pytest -import pandas.util._test_decorators as td - -import pandas as pd from pandas import DataFrame jinja2 = pytest.importorskip("jinja2") -from pandas.io.formats.style import Styler def bar_grad(a=None, b=None, c=None, d=None): @@ -23,7 +18,7 @@ def bar_grad(a=None, b=None, c=None, d=None): ] -class TestStyler: +class TestStylerBarAlign: def test_bar_align_left(self): df = DataFrame({"A": [0, 1, 2]}) result = df.style.bar()._compute().ctx @@ -409,248 +404,3 @@ def test_bar_bad_align_raises(self): msg = "`align` must be one of {'left', 'zero',' mid'}" with pytest.raises(ValueError, match=msg): df.style.bar(align="poorly", color=["#d65f5f", "#5fba7d"]) - - def test_highlight_null(self): - df = DataFrame({"A": [0, np.nan]}) - result = df.style.highlight_null()._compute().ctx - expected = {(1, 0): [("background-color", "red")]} - assert result == expected - - def test_highlight_null_subset(self): - # GH 31345 - df = DataFrame({"A": [0, np.nan], "B": [0, np.nan]}) - result = ( - df.style.highlight_null(null_color="red", subset=["A"]) - .highlight_null(null_color="green", subset=["B"]) - ._compute() - .ctx - ) - expected = { - (1, 0): [("background-color", "red")], - (1, 1): [("background-color", "green")], - } - assert result == expected - - def test_highlight_max(self): - df = DataFrame([[1, 2], [3, 4]], columns=["A", "B"]) - css_seq = [("background-color", "yellow")] - # max(df) = min(-df) - for max_ in [True, False]: - if max_: - attr = "highlight_max" - else: - df = -df - attr = "highlight_min" - result = getattr(df.style, attr)()._compute().ctx - assert result[(1, 1)] == css_seq - - result = getattr(df.style, attr)(color="green")._compute().ctx - assert result[(1, 1)] == [("background-color", "green")] - - result = getattr(df.style, attr)(subset="A")._compute().ctx - assert result[(1, 0)] == css_seq - - result = getattr(df.style, attr)(axis=0)._compute().ctx - expected = { - (1, 0): css_seq, - (1, 1): css_seq, - } - assert result == expected - - result = getattr(df.style, attr)(axis=1)._compute().ctx - expected = { - (0, 1): css_seq, - (1, 1): css_seq, - } - assert result == expected - - # separate since we can't negate the strs - df["C"] = ["a", "b"] - result = df.style.highlight_max()._compute().ctx - expected = {(1, 1): css_seq} - - result = df.style.highlight_min()._compute().ctx - expected = {(0, 0): css_seq} - - @pytest.mark.parametrize( - "ttips", - [ - DataFrame( - data=[["Min", "Max"], [np.nan, ""]], - columns=["A", "B"], - index=["a", "b"], - ), - DataFrame(data=[["Max", "Min"]], columns=["B", "A"], index=["a"]), - DataFrame( - data=[["Min", "Max", None]], columns=["A", "B", "C"], index=["a"] - ), - ], - ) - def test_tooltip_render(self, ttips): - # GH 21266 - df = DataFrame(data=[[0, 3], [1, 2]], columns=["A", "B"], index=["a", "b"]) - s = Styler(df, uuid_len=0).set_tooltips(ttips).render() - - # test tooltip table level class - assert "#T__ .pd-t {\n visibility: hidden;\n" in s - - # test 'Min' tooltip added - assert ( - "#T__ #T__row0_col0:hover .pd-t {\n visibility: visible;\n}\n" - + '#T__ #T__row0_col0 .pd-t::after {\n content: "Min";\n}' - in s - ) - assert ( - '0' - + "" - in s - ) - - # test 'Max' tooltip added - assert ( - "#T__ #T__row0_col1:hover .pd-t {\n visibility: visible;\n}\n" - + '#T__ #T__row0_col1 .pd-t::after {\n content: "Max";\n}' - in s - ) - assert ( - '3' - + "" - in s - ) - - def test_tooltip_reindex(self): - # GH 39317 - df = DataFrame( - data=[[0, 1, 2], [3, 4, 5], [6, 7, 8]], columns=[0, 1, 2], index=[0, 1, 2] - ) - ttips = DataFrame( - data=[["Mi", "Ma"], ["Mu", "Mo"]], - columns=[0, 2], - index=[0, 2], - ) - s = Styler(df, uuid_len=0).set_tooltips(DataFrame(ttips)).render() - assert '#T__ #T__row0_col0 .pd-t::after {\n content: "Mi";\n}' in s - assert '#T__ #T__row0_col2 .pd-t::after {\n content: "Ma";\n}' in s - assert '#T__ #T__row2_col0 .pd-t::after {\n content: "Mu";\n}' in s - assert '#T__ #T__row2_col2 .pd-t::after {\n content: "Mo";\n}' in s - - def test_tooltip_ignored(self): - # GH 21266 - df = DataFrame(data=[[0, 1], [2, 3]]) - s = Styler(df).set_tooltips_class("pd-t").render() # no set_tooltips() - assert '' in s - assert '' not in s - - def test_tooltip_class(self): - # GH 21266 - df = DataFrame(data=[[0, 1], [2, 3]]) - s = ( - Styler(df, uuid_len=0) - .set_tooltips(DataFrame([["tooltip"]])) - .set_tooltips_class(name="other-class", properties=[("color", "green")]) - .render() - ) - assert "#T__ .other-class {\n color: green;\n" in s - assert '#T__ #T__row0_col0 .other-class::after {\n content: "tooltip";\n' in s - - # GH 39563 - s = ( - Styler(df, uuid_len=0) - .set_tooltips(DataFrame([["tooltip"]])) - .set_tooltips_class(name="other-class", properties="color:green;color:red;") - .render() - ) - assert "#T__ .other-class {\n color: green;\n color: red;\n}" in s - - -@td.skip_if_no_mpl -class TestStylerMatplotlibDep: - def test_background_gradient(self): - df = DataFrame([[1, 2], [2, 4]], columns=["A", "B"]) - - for c_map in [None, "YlOrRd"]: - result = df.style.background_gradient(cmap=c_map)._compute().ctx - assert all("#" in x[0][1] for x in result.values()) - assert result[(0, 0)] == result[(0, 1)] - assert result[(1, 0)] == result[(1, 1)] - - result = ( - df.style.background_gradient(subset=pd.IndexSlice[1, "A"])._compute().ctx - ) - - assert result[(1, 0)] == [("background-color", "#fff7fb"), ("color", "#000000")] - - @pytest.mark.parametrize( - "c_map,expected", - [ - ( - None, - { - (0, 0): [("background-color", "#440154"), ("color", "#f1f1f1")], - (1, 0): [("background-color", "#fde725"), ("color", "#000000")], - }, - ), - ( - "YlOrRd", - { - (0, 0): [("background-color", "#ffffcc"), ("color", "#000000")], - (1, 0): [("background-color", "#800026"), ("color", "#f1f1f1")], - }, - ), - ], - ) - def test_text_color_threshold(self, c_map, expected): - df = DataFrame([1, 2], columns=["A"]) - result = df.style.background_gradient(cmap=c_map)._compute().ctx - assert result == expected - - @pytest.mark.parametrize("text_color_threshold", [1.1, "1", -1, [2, 2]]) - def test_text_color_threshold_raises(self, text_color_threshold): - df = DataFrame([[1, 2], [2, 4]], columns=["A", "B"]) - msg = "`text_color_threshold` must be a value from 0 to 1." - with pytest.raises(ValueError, match=msg): - df.style.background_gradient( - text_color_threshold=text_color_threshold - )._compute() - - @td.skip_if_no_mpl - def test_background_gradient_axis(self): - df = DataFrame([[1, 2], [2, 4]], columns=["A", "B"]) - - low = [("background-color", "#f7fbff"), ("color", "#000000")] - high = [("background-color", "#08306b"), ("color", "#f1f1f1")] - mid = [("background-color", "#abd0e6"), ("color", "#000000")] - result = df.style.background_gradient(cmap="Blues", axis=0)._compute().ctx - assert result[(0, 0)] == low - assert result[(0, 1)] == low - assert result[(1, 0)] == high - assert result[(1, 1)] == high - - result = df.style.background_gradient(cmap="Blues", axis=1)._compute().ctx - assert result[(0, 0)] == low - assert result[(0, 1)] == high - assert result[(1, 0)] == low - assert result[(1, 1)] == high - - result = df.style.background_gradient(cmap="Blues", axis=None)._compute().ctx - assert result[(0, 0)] == low - assert result[(0, 1)] == mid - assert result[(1, 0)] == mid - assert result[(1, 1)] == high - - def test_background_gradient_vmin_vmax(self): - # GH 12145 - df = DataFrame(range(5)) - ctx = df.style.background_gradient(vmin=1, vmax=3)._compute().ctx - assert ctx[(0, 0)] == ctx[(1, 0)] - assert ctx[(4, 0)] == ctx[(3, 0)] - - def test_background_gradient_int64(self): - # GH 28869 - df1 = pd.Series(range(3)).to_frame() - df2 = pd.Series(range(3), dtype="Int64").to_frame() - ctx1 = df1.style.background_gradient()._compute().ctx - ctx2 = df2.style.background_gradient()._compute().ctx - assert ctx2[(0, 0)] == ctx1[(0, 0)] - assert ctx2[(1, 0)] == ctx1[(1, 0)] - assert ctx2[(2, 0)] == ctx1[(2, 0)] diff --git a/pandas/tests/io/formats/style/test_highlight.py b/pandas/tests/io/formats/style/test_highlight.py new file mode 100644 index 0000000000000..f7c048db7872c --- /dev/null +++ b/pandas/tests/io/formats/style/test_highlight.py @@ -0,0 +1,70 @@ +import numpy as np +import pytest + +from pandas import DataFrame + +jinja2 = pytest.importorskip("jinja2") + + +class TestStylerHighlight: + def test_highlight_null(self): + df = DataFrame({"A": [0, np.nan]}) + result = df.style.highlight_null()._compute().ctx + expected = {(1, 0): [("background-color", "red")]} + assert result == expected + + def test_highlight_null_subset(self): + # GH 31345 + df = DataFrame({"A": [0, np.nan], "B": [0, np.nan]}) + result = ( + df.style.highlight_null(null_color="red", subset=["A"]) + .highlight_null(null_color="green", subset=["B"]) + ._compute() + .ctx + ) + expected = { + (1, 0): [("background-color", "red")], + (1, 1): [("background-color", "green")], + } + assert result == expected + + def test_highlight_max(self): + df = DataFrame([[1, 2], [3, 4]], columns=["A", "B"]) + css_seq = [("background-color", "yellow")] + # max(df) = min(-df) + for max_ in [True, False]: + if max_: + attr = "highlight_max" + else: + df = -df + attr = "highlight_min" + result = getattr(df.style, attr)()._compute().ctx + assert result[(1, 1)] == css_seq + + result = getattr(df.style, attr)(color="green")._compute().ctx + assert result[(1, 1)] == [("background-color", "green")] + + result = getattr(df.style, attr)(subset="A")._compute().ctx + assert result[(1, 0)] == css_seq + + result = getattr(df.style, attr)(axis=0)._compute().ctx + expected = { + (1, 0): css_seq, + (1, 1): css_seq, + } + assert result == expected + + result = getattr(df.style, attr)(axis=1)._compute().ctx + expected = { + (0, 1): css_seq, + (1, 1): css_seq, + } + assert result == expected + + # separate since we can't negate the strs + df["C"] = ["a", "b"] + result = df.style.highlight_max()._compute().ctx + expected = {(1, 1): css_seq} + + result = df.style.highlight_min()._compute().ctx + expected = {(0, 0): css_seq} diff --git a/pandas/tests/io/formats/style/test_tooltip.py b/pandas/tests/io/formats/style/test_tooltip.py new file mode 100644 index 0000000000000..0510a19813ee2 --- /dev/null +++ b/pandas/tests/io/formats/style/test_tooltip.py @@ -0,0 +1,99 @@ +import numpy as np +import pytest + +from pandas import DataFrame + +jinja2 = pytest.importorskip("jinja2") +from pandas.io.formats.style import Styler + + +class TestStylerTooltip: + @pytest.mark.parametrize( + "ttips", + [ + DataFrame( + data=[["Min", "Max"], [np.nan, ""]], + columns=["A", "B"], + index=["a", "b"], + ), + DataFrame(data=[["Max", "Min"]], columns=["B", "A"], index=["a"]), + DataFrame( + data=[["Min", "Max", None]], columns=["A", "B", "C"], index=["a"] + ), + ], + ) + def test_tooltip_render(self, ttips): + # GH 21266 + df = DataFrame(data=[[0, 3], [1, 2]], columns=["A", "B"], index=["a", "b"]) + s = Styler(df, uuid_len=0).set_tooltips(ttips).render() + + # test tooltip table level class + assert "#T__ .pd-t {\n visibility: hidden;\n" in s + + # test 'Min' tooltip added + assert ( + "#T__ #T__row0_col0:hover .pd-t {\n visibility: visible;\n}\n" + + '#T__ #T__row0_col0 .pd-t::after {\n content: "Min";\n}' + in s + ) + assert ( + '0' + + "" + in s + ) + + # test 'Max' tooltip added + assert ( + "#T__ #T__row0_col1:hover .pd-t {\n visibility: visible;\n}\n" + + '#T__ #T__row0_col1 .pd-t::after {\n content: "Max";\n}' + in s + ) + assert ( + '3' + + "" + in s + ) + + def test_tooltip_reindex(self): + # GH 39317 + df = DataFrame( + data=[[0, 1, 2], [3, 4, 5], [6, 7, 8]], columns=[0, 1, 2], index=[0, 1, 2] + ) + ttips = DataFrame( + data=[["Mi", "Ma"], ["Mu", "Mo"]], + columns=[0, 2], + index=[0, 2], + ) + s = Styler(df, uuid_len=0).set_tooltips(DataFrame(ttips)).render() + assert '#T__ #T__row0_col0 .pd-t::after {\n content: "Mi";\n}' in s + assert '#T__ #T__row0_col2 .pd-t::after {\n content: "Ma";\n}' in s + assert '#T__ #T__row2_col0 .pd-t::after {\n content: "Mu";\n}' in s + assert '#T__ #T__row2_col2 .pd-t::after {\n content: "Mo";\n}' in s + + def test_tooltip_ignored(self): + # GH 21266 + df = DataFrame(data=[[0, 1], [2, 3]]) + s = Styler(df).set_tooltips_class("pd-t").render() # no set_tooltips() + assert '' in s + assert '' not in s + + def test_tooltip_css_class(self): + # GH 21266 + df = DataFrame(data=[[0, 1], [2, 3]]) + s = ( + Styler(df, uuid_len=0) + .set_tooltips(DataFrame([["tooltip"]])) + .set_tooltips_class(name="other-class", properties=[("color", "green")]) + .render() + ) + assert "#T__ .other-class {\n color: green;\n" in s + assert '#T__ #T__row0_col0 .other-class::after {\n content: "tooltip";\n' in s + + # GH 39563 + s = ( + Styler(df, uuid_len=0) + .set_tooltips(DataFrame([["tooltip"]])) + .set_tooltips_class(name="other-class", properties="color:green;color:red;") + .render() + ) + assert "#T__ .other-class {\n color: green;\n color: red;\n}" in s diff --git a/pandas/tests/plotting/test_style.py b/pandas/tests/plotting/test_style.py index 3c48eeaccbf34..84e591beb9928 100644 --- a/pandas/tests/plotting/test_style.py +++ b/pandas/tests/plotting/test_style.py @@ -1,6 +1,12 @@ import pytest -from pandas import Series +import pandas.util._test_decorators as td + +from pandas import ( + DataFrame, + IndexSlice, + Series, +) pytest.importorskip("matplotlib") from pandas.plotting._matplotlib.style import get_standard_colors @@ -157,3 +163,94 @@ def test_empty_color_raises(self, color): def test_bad_color_raises(self, color): with pytest.raises(ValueError, match="Invalid color"): get_standard_colors(color=color, num_colors=5) + + +@td.skip_if_no_mpl +class TestStylerMatplotlibDep: + def test_background_gradient(self): + df = DataFrame([[1, 2], [2, 4]], columns=["A", "B"]) + + for c_map in [None, "YlOrRd"]: + result = df.style.background_gradient(cmap=c_map)._compute().ctx + assert all("#" in x[0][1] for x in result.values()) + assert result[(0, 0)] == result[(0, 1)] + assert result[(1, 0)] == result[(1, 1)] + + result = df.style.background_gradient(subset=IndexSlice[1, "A"])._compute().ctx + + assert result[(1, 0)] == [("background-color", "#fff7fb"), ("color", "#000000")] + + @pytest.mark.parametrize( + "c_map,expected", + [ + ( + None, + { + (0, 0): [("background-color", "#440154"), ("color", "#f1f1f1")], + (1, 0): [("background-color", "#fde725"), ("color", "#000000")], + }, + ), + ( + "YlOrRd", + { + (0, 0): [("background-color", "#ffffcc"), ("color", "#000000")], + (1, 0): [("background-color", "#800026"), ("color", "#f1f1f1")], + }, + ), + ], + ) + def test_text_color_threshold(self, c_map, expected): + df = DataFrame([1, 2], columns=["A"]) + result = df.style.background_gradient(cmap=c_map)._compute().ctx + assert result == expected + + @pytest.mark.parametrize("text_color_threshold", [1.1, "1", -1, [2, 2]]) + def test_text_color_threshold_raises(self, text_color_threshold): + df = DataFrame([[1, 2], [2, 4]], columns=["A", "B"]) + msg = "`text_color_threshold` must be a value from 0 to 1." + with pytest.raises(ValueError, match=msg): + df.style.background_gradient( + text_color_threshold=text_color_threshold + )._compute() + + @td.skip_if_no_mpl + def test_background_gradient_axis(self): + df = DataFrame([[1, 2], [2, 4]], columns=["A", "B"]) + + low = [("background-color", "#f7fbff"), ("color", "#000000")] + high = [("background-color", "#08306b"), ("color", "#f1f1f1")] + mid = [("background-color", "#abd0e6"), ("color", "#000000")] + result = df.style.background_gradient(cmap="Blues", axis=0)._compute().ctx + assert result[(0, 0)] == low + assert result[(0, 1)] == low + assert result[(1, 0)] == high + assert result[(1, 1)] == high + + result = df.style.background_gradient(cmap="Blues", axis=1)._compute().ctx + assert result[(0, 0)] == low + assert result[(0, 1)] == high + assert result[(1, 0)] == low + assert result[(1, 1)] == high + + result = df.style.background_gradient(cmap="Blues", axis=None)._compute().ctx + assert result[(0, 0)] == low + assert result[(0, 1)] == mid + assert result[(1, 0)] == mid + assert result[(1, 1)] == high + + def test_background_gradient_vmin_vmax(self): + # GH 12145 + df = DataFrame(range(5)) + ctx = df.style.background_gradient(vmin=1, vmax=3)._compute().ctx + assert ctx[(0, 0)] == ctx[(1, 0)] + assert ctx[(4, 0)] == ctx[(3, 0)] + + def test_background_gradient_int64(self): + # GH 28869 + df1 = Series(range(3)).to_frame() + df2 = Series(range(3), dtype="Int64").to_frame() + ctx1 = df1.style.background_gradient()._compute().ctx + ctx2 = df2.style.background_gradient()._compute().ctx + assert ctx2[(0, 0)] == ctx1[(0, 0)] + assert ctx2[(1, 0)] == ctx1[(1, 0)] + assert ctx2[(2, 0)] == ctx1[(2, 0)] From 8d160dc00a66991893bd59c6c110c67265984235 Mon Sep 17 00:00:00 2001 From: "JHM Darbyshire (iMac)" Date: Mon, 22 Feb 2021 08:37:35 +0100 Subject: [PATCH 3/7] re insert that lost on merge --- pandas/tests/plotting/test_style.py | 29 +++++++++++++++++++---------- 1 file changed, 19 insertions(+), 10 deletions(-) diff --git a/pandas/tests/plotting/test_style.py b/pandas/tests/plotting/test_style.py index 84e591beb9928..f8e02b443ca68 100644 --- a/pandas/tests/plotting/test_style.py +++ b/pandas/tests/plotting/test_style.py @@ -1,3 +1,4 @@ +import numpy as np import pytest import pandas.util._test_decorators as td @@ -181,28 +182,36 @@ def test_background_gradient(self): assert result[(1, 0)] == [("background-color", "#fff7fb"), ("color", "#000000")] @pytest.mark.parametrize( - "c_map,expected", + "cmap, expected", [ ( - None, + "PuBu", { - (0, 0): [("background-color", "#440154"), ("color", "#f1f1f1")], - (1, 0): [("background-color", "#fde725"), ("color", "#000000")], + (4, 5): [("background-color", "#86b0d3"), ("color", "#000000")], + (4, 6): [("background-color", "#83afd3"), ("color", "#f1f1f1")], }, ), ( "YlOrRd", { - (0, 0): [("background-color", "#ffffcc"), ("color", "#000000")], - (1, 0): [("background-color", "#800026"), ("color", "#f1f1f1")], + (4, 8): [("background-color", "#fd913e"), ("color", "#000000")], + (4, 9): [("background-color", "#fd8f3d"), ("color", "#f1f1f1")], + }, + ), + ( + None, + { + (7, 0): [("background-color", "#48c16e"), ("color", "#f1f1f1")], + (7, 1): [("background-color", "#4cc26c"), ("color", "#000000")], }, ), ], ) - def test_text_color_threshold(self, c_map, expected): - df = DataFrame([1, 2], columns=["A"]) - result = df.style.background_gradient(cmap=c_map)._compute().ctx - assert result == expected + def test_text_color_threshold(self, cmap, expected): + df = DataFrame(np.arange(100).reshape(10, 10)) + result = df.style.background_gradient(cmap=cmap, axis=None)._compute().ctx + for k in expected.keys(): + assert result[k] == expected[k] @pytest.mark.parametrize("text_color_threshold", [1.1, "1", -1, [2, 2]]) def test_text_color_threshold_raises(self, text_color_threshold): From c8c05ca55d36262b00b633c15f301b8a8be928d6 Mon Sep 17 00:00:00 2001 From: "JHM Darbyshire (iMac)" Date: Mon, 22 Feb 2021 08:56:02 +0100 Subject: [PATCH 4/7] remove unnecessary decorator in matplotlib test file --- pandas/tests/plotting/test_style.py | 4 ---- 1 file changed, 4 deletions(-) diff --git a/pandas/tests/plotting/test_style.py b/pandas/tests/plotting/test_style.py index f8e02b443ca68..afcc0cc9fd998 100644 --- a/pandas/tests/plotting/test_style.py +++ b/pandas/tests/plotting/test_style.py @@ -1,8 +1,6 @@ import numpy as np import pytest -import pandas.util._test_decorators as td - from pandas import ( DataFrame, IndexSlice, @@ -166,7 +164,6 @@ def test_bad_color_raises(self, color): get_standard_colors(color=color, num_colors=5) -@td.skip_if_no_mpl class TestStylerMatplotlibDep: def test_background_gradient(self): df = DataFrame([[1, 2], [2, 4]], columns=["A", "B"]) @@ -222,7 +219,6 @@ def test_text_color_threshold_raises(self, text_color_threshold): text_color_threshold=text_color_threshold )._compute() - @td.skip_if_no_mpl def test_background_gradient_axis(self): df = DataFrame([[1, 2], [2, 4]], columns=["A", "B"]) From 1efe5b1c9ddae2c45fac5beceeaee9226975fb5b Mon Sep 17 00:00:00 2001 From: "JHM Darbyshire (iMac)" Date: Mon, 22 Feb 2021 16:58:11 +0100 Subject: [PATCH 5/7] matplotlib tests in right place --- .../tests/io/formats/style/test_matplotlib.py | 107 ++++++++++++++++++ pandas/tests/plotting/test_style.py | 104 +---------------- 2 files changed, 108 insertions(+), 103 deletions(-) create mode 100644 pandas/tests/io/formats/style/test_matplotlib.py diff --git a/pandas/tests/io/formats/style/test_matplotlib.py b/pandas/tests/io/formats/style/test_matplotlib.py new file mode 100644 index 0000000000000..5c12e8837df40 --- /dev/null +++ b/pandas/tests/io/formats/style/test_matplotlib.py @@ -0,0 +1,107 @@ +import numpy as np +import pytest + +from pandas import ( + DataFrame, + IndexSlice, + Series, +) + +pytest.importorskip("matplotlib") + + +class TestStylerMatplotlibDep: + def test_background_gradient(self): + df = DataFrame([[1, 2], [2, 4]], columns=["A", "B"]) + + for c_map in [None, "YlOrRd"]: + result = df.style.background_gradient(cmap=c_map)._compute().ctx + assert all("#" in x[0][1] for x in result.values()) + assert result[(0, 0)] == result[(0, 1)] + assert result[(1, 0)] == result[(1, 1)] + + result = df.style.background_gradient(subset=IndexSlice[1, "A"])._compute().ctx + + assert result[(1, 0)] == [("background-color", "#fff7fb"), ("color", "#000000")] + + @pytest.mark.parametrize( + "cmap, expected", + [ + ( + "PuBu", + { + (4, 5): [("background-color", "#86b0d3"), ("color", "#000000")], + (4, 6): [("background-color", "#83afd3"), ("color", "#f1f1f1")], + }, + ), + ( + "YlOrRd", + { + (4, 8): [("background-color", "#fd913e"), ("color", "#000000")], + (4, 9): [("background-color", "#fd8f3d"), ("color", "#f1f1f1")], + }, + ), + ( + None, + { + (7, 0): [("background-color", "#48c16e"), ("color", "#f1f1f1")], + (7, 1): [("background-color", "#4cc26c"), ("color", "#000000")], + }, + ), + ], + ) + def test_text_color_threshold(self, cmap, expected): + df = DataFrame(np.arange(100).reshape(10, 10)) + result = df.style.background_gradient(cmap=cmap, axis=None)._compute().ctx + for k in expected.keys(): + assert result[k] == expected[k] + + @pytest.mark.parametrize("text_color_threshold", [1.1, "1", -1, [2, 2]]) + def test_text_color_threshold_raises(self, text_color_threshold): + df = DataFrame([[1, 2], [2, 4]], columns=["A", "B"]) + msg = "`text_color_threshold` must be a value from 0 to 1." + with pytest.raises(ValueError, match=msg): + df.style.background_gradient( + text_color_threshold=text_color_threshold + )._compute() + + def test_background_gradient_axis(self): + df = DataFrame([[1, 2], [2, 4]], columns=["A", "B"]) + + low = [("background-color", "#f7fbff"), ("color", "#000000")] + high = [("background-color", "#08306b"), ("color", "#f1f1f1")] + mid = [("background-color", "#abd0e6"), ("color", "#000000")] + result = df.style.background_gradient(cmap="Blues", axis=0)._compute().ctx + assert result[(0, 0)] == low + assert result[(0, 1)] == low + assert result[(1, 0)] == high + assert result[(1, 1)] == high + + result = df.style.background_gradient(cmap="Blues", axis=1)._compute().ctx + assert result[(0, 0)] == low + assert result[(0, 1)] == high + assert result[(1, 0)] == low + assert result[(1, 1)] == high + + result = df.style.background_gradient(cmap="Blues", axis=None)._compute().ctx + assert result[(0, 0)] == low + assert result[(0, 1)] == mid + assert result[(1, 0)] == mid + assert result[(1, 1)] == high + + def test_background_gradient_vmin_vmax(self): + # GH 12145 + df = DataFrame(range(5)) + ctx = df.style.background_gradient(vmin=1, vmax=3)._compute().ctx + assert ctx[(0, 0)] == ctx[(1, 0)] + assert ctx[(4, 0)] == ctx[(3, 0)] + + def test_background_gradient_int64(self): + # GH 28869 + df1 = Series(range(3)).to_frame() + df2 = Series(range(3), dtype="Int64").to_frame() + ctx1 = df1.style.background_gradient()._compute().ctx + ctx2 = df2.style.background_gradient()._compute().ctx + assert ctx2[(0, 0)] == ctx1[(0, 0)] + assert ctx2[(1, 0)] == ctx1[(1, 0)] + assert ctx2[(2, 0)] == ctx1[(2, 0)] diff --git a/pandas/tests/plotting/test_style.py b/pandas/tests/plotting/test_style.py index afcc0cc9fd998..3c48eeaccbf34 100644 --- a/pandas/tests/plotting/test_style.py +++ b/pandas/tests/plotting/test_style.py @@ -1,11 +1,6 @@ -import numpy as np import pytest -from pandas import ( - DataFrame, - IndexSlice, - Series, -) +from pandas import Series pytest.importorskip("matplotlib") from pandas.plotting._matplotlib.style import get_standard_colors @@ -162,100 +157,3 @@ def test_empty_color_raises(self, color): def test_bad_color_raises(self, color): with pytest.raises(ValueError, match="Invalid color"): get_standard_colors(color=color, num_colors=5) - - -class TestStylerMatplotlibDep: - def test_background_gradient(self): - df = DataFrame([[1, 2], [2, 4]], columns=["A", "B"]) - - for c_map in [None, "YlOrRd"]: - result = df.style.background_gradient(cmap=c_map)._compute().ctx - assert all("#" in x[0][1] for x in result.values()) - assert result[(0, 0)] == result[(0, 1)] - assert result[(1, 0)] == result[(1, 1)] - - result = df.style.background_gradient(subset=IndexSlice[1, "A"])._compute().ctx - - assert result[(1, 0)] == [("background-color", "#fff7fb"), ("color", "#000000")] - - @pytest.mark.parametrize( - "cmap, expected", - [ - ( - "PuBu", - { - (4, 5): [("background-color", "#86b0d3"), ("color", "#000000")], - (4, 6): [("background-color", "#83afd3"), ("color", "#f1f1f1")], - }, - ), - ( - "YlOrRd", - { - (4, 8): [("background-color", "#fd913e"), ("color", "#000000")], - (4, 9): [("background-color", "#fd8f3d"), ("color", "#f1f1f1")], - }, - ), - ( - None, - { - (7, 0): [("background-color", "#48c16e"), ("color", "#f1f1f1")], - (7, 1): [("background-color", "#4cc26c"), ("color", "#000000")], - }, - ), - ], - ) - def test_text_color_threshold(self, cmap, expected): - df = DataFrame(np.arange(100).reshape(10, 10)) - result = df.style.background_gradient(cmap=cmap, axis=None)._compute().ctx - for k in expected.keys(): - assert result[k] == expected[k] - - @pytest.mark.parametrize("text_color_threshold", [1.1, "1", -1, [2, 2]]) - def test_text_color_threshold_raises(self, text_color_threshold): - df = DataFrame([[1, 2], [2, 4]], columns=["A", "B"]) - msg = "`text_color_threshold` must be a value from 0 to 1." - with pytest.raises(ValueError, match=msg): - df.style.background_gradient( - text_color_threshold=text_color_threshold - )._compute() - - def test_background_gradient_axis(self): - df = DataFrame([[1, 2], [2, 4]], columns=["A", "B"]) - - low = [("background-color", "#f7fbff"), ("color", "#000000")] - high = [("background-color", "#08306b"), ("color", "#f1f1f1")] - mid = [("background-color", "#abd0e6"), ("color", "#000000")] - result = df.style.background_gradient(cmap="Blues", axis=0)._compute().ctx - assert result[(0, 0)] == low - assert result[(0, 1)] == low - assert result[(1, 0)] == high - assert result[(1, 1)] == high - - result = df.style.background_gradient(cmap="Blues", axis=1)._compute().ctx - assert result[(0, 0)] == low - assert result[(0, 1)] == high - assert result[(1, 0)] == low - assert result[(1, 1)] == high - - result = df.style.background_gradient(cmap="Blues", axis=None)._compute().ctx - assert result[(0, 0)] == low - assert result[(0, 1)] == mid - assert result[(1, 0)] == mid - assert result[(1, 1)] == high - - def test_background_gradient_vmin_vmax(self): - # GH 12145 - df = DataFrame(range(5)) - ctx = df.style.background_gradient(vmin=1, vmax=3)._compute().ctx - assert ctx[(0, 0)] == ctx[(1, 0)] - assert ctx[(4, 0)] == ctx[(3, 0)] - - def test_background_gradient_int64(self): - # GH 28869 - df1 = Series(range(3)).to_frame() - df2 = Series(range(3), dtype="Int64").to_frame() - ctx1 = df1.style.background_gradient()._compute().ctx - ctx2 = df2.style.background_gradient()._compute().ctx - assert ctx2[(0, 0)] == ctx1[(0, 0)] - assert ctx2[(1, 0)] == ctx1[(1, 0)] - assert ctx2[(2, 0)] == ctx1[(2, 0)] From 36969912c155f68a6c9f6daa7adf8d83de134cdc Mon Sep 17 00:00:00 2001 From: "JHM Darbyshire (iMac)" Date: Mon, 22 Feb 2021 17:06:01 +0100 Subject: [PATCH 6/7] remove jinja dependency for some tests --- pandas/tests/io/formats/style/test_align.py | 2 -- pandas/tests/io/formats/style/test_highlight.py | 3 --- 2 files changed, 5 deletions(-) diff --git a/pandas/tests/io/formats/style/test_align.py b/pandas/tests/io/formats/style/test_align.py index 60ebff2231a70..83b0fb46f4dd9 100644 --- a/pandas/tests/io/formats/style/test_align.py +++ b/pandas/tests/io/formats/style/test_align.py @@ -2,8 +2,6 @@ from pandas import DataFrame -jinja2 = pytest.importorskip("jinja2") - def bar_grad(a=None, b=None, c=None, d=None): """Used in multiple tests to simplify formatting of expected result""" diff --git a/pandas/tests/io/formats/style/test_highlight.py b/pandas/tests/io/formats/style/test_highlight.py index f7c048db7872c..7e923cead1b1d 100644 --- a/pandas/tests/io/formats/style/test_highlight.py +++ b/pandas/tests/io/formats/style/test_highlight.py @@ -1,10 +1,7 @@ import numpy as np -import pytest from pandas import DataFrame -jinja2 = pytest.importorskip("jinja2") - class TestStylerHighlight: def test_highlight_null(self): From 5b9692b0932574e5a79de58f995f70da6475c74b Mon Sep 17 00:00:00 2001 From: "JHM Darbyshire (iMac)" Date: Mon, 22 Feb 2021 18:18:14 +0100 Subject: [PATCH 7/7] set dependencies --- pandas/tests/io/formats/style/test_align.py | 2 ++ pandas/tests/io/formats/style/test_highlight.py | 3 +++ pandas/tests/io/formats/style/test_matplotlib.py | 1 + pandas/tests/io/formats/style/test_tooltip.py | 2 +- 4 files changed, 7 insertions(+), 1 deletion(-) diff --git a/pandas/tests/io/formats/style/test_align.py b/pandas/tests/io/formats/style/test_align.py index 83b0fb46f4dd9..f81c1fbd6d85e 100644 --- a/pandas/tests/io/formats/style/test_align.py +++ b/pandas/tests/io/formats/style/test_align.py @@ -2,6 +2,8 @@ from pandas import DataFrame +pytest.importorskip("jinja2") + def bar_grad(a=None, b=None, c=None, d=None): """Used in multiple tests to simplify formatting of expected result""" diff --git a/pandas/tests/io/formats/style/test_highlight.py b/pandas/tests/io/formats/style/test_highlight.py index 7e923cead1b1d..e02e1f012c662 100644 --- a/pandas/tests/io/formats/style/test_highlight.py +++ b/pandas/tests/io/formats/style/test_highlight.py @@ -1,7 +1,10 @@ import numpy as np +import pytest from pandas import DataFrame +pytest.importorskip("jinja2") + class TestStylerHighlight: def test_highlight_null(self): diff --git a/pandas/tests/io/formats/style/test_matplotlib.py b/pandas/tests/io/formats/style/test_matplotlib.py index 5c12e8837df40..f01e818e40b22 100644 --- a/pandas/tests/io/formats/style/test_matplotlib.py +++ b/pandas/tests/io/formats/style/test_matplotlib.py @@ -8,6 +8,7 @@ ) pytest.importorskip("matplotlib") +pytest.importorskip("jinja2") class TestStylerMatplotlibDep: diff --git a/pandas/tests/io/formats/style/test_tooltip.py b/pandas/tests/io/formats/style/test_tooltip.py index 0510a19813ee2..7aebb6fadc7b1 100644 --- a/pandas/tests/io/formats/style/test_tooltip.py +++ b/pandas/tests/io/formats/style/test_tooltip.py @@ -3,7 +3,7 @@ from pandas import DataFrame -jinja2 = pytest.importorskip("jinja2") +pytest.importorskip("jinja2") from pandas.io.formats.style import Styler