From 0c6c84fc89804bbd32e070e59bbbea70f9b9e689 Mon Sep 17 00:00:00 2001 From: "JHM Darbyshire (iMac)" Date: Mon, 17 Apr 2023 20:09:09 +0200 Subject: [PATCH 1/7] REF: Styler.applymap -> map --- pandas/io/formats/style.py | 93 ++++++++++++++++++++++++++++++-------- 1 file changed, 74 insertions(+), 19 deletions(-) diff --git a/pandas/io/formats/style.py b/pandas/io/formats/style.py index e2c5ed2ea92b6..33951f3570507 100644 --- a/pandas/io/formats/style.py +++ b/pandas/io/formats/style.py @@ -1812,7 +1812,7 @@ def _apply_index( if method == "apply": result = data.apply(func, axis=0, **kwargs) - elif method == "applymap": + elif method == "map": result = data.map(func, **kwargs) self._update_ctx_header(result, axis) @@ -1821,7 +1821,7 @@ def _apply_index( @doc( this="apply", wise="level-wise", - alt="applymap", + alt="map", altwise="elementwise", func="take a Series and return a string array of the same length", input_note="the index as a Series, if an Index, or a level of a MultiIndex", @@ -1844,6 +1844,9 @@ def apply_index( .. versionadded:: 1.4.0 + .. versionadded:: 2.1.0 + Styler.applymap_index was deprecated and renamed to Styler.map_index. + Parameters ---------- func : function @@ -1863,7 +1866,7 @@ def apply_index( -------- Styler.{alt}_index: Apply a CSS-styling function to headers {altwise}. Styler.apply: Apply a CSS-styling function column-wise, row-wise, or table-wise. - Styler.applymap: Apply a CSS-styling function elementwise. + Styler.map: Apply a CSS-styling function elementwise. Notes ----- @@ -1904,7 +1907,7 @@ def apply_index( @doc( apply_index, - this="applymap", + this="map", wise="elementwise", alt="apply", altwise="level-wise", @@ -1915,7 +1918,7 @@ def apply_index( ret='"background-color: yellow;" if v == "B" else None', ret2='"background-color: yellow;" if "x" in v else None', ) - def applymap_index( + def map_index( self, func: Callable, axis: AxisInt | str = 0, @@ -1925,16 +1928,45 @@ def applymap_index( self._todo.append( ( lambda instance: getattr(instance, "_apply_index"), - (func, axis, level, "applymap"), + (func, axis, level, "map"), kwargs, ) ) return self - def _applymap( - self, func: Callable, subset: Subset | None = None, **kwargs + def applymap_index( + self, + func: Callable, + axis: AxisInt | str = 0, + level: Level | list[Level] | None = None, + **kwargs, ) -> Styler: - func = partial(func, **kwargs) # applymap doesn't take kwargs? + """ + Apply a CSS-styling function to the index or column headers, elementwise. + + .. deprecated:: 2.1.0 + + Styler.applymap_index has been deprecated. Use Styler.map_index instead. + + Parameters + ---------- + func : function + ``func`` should take a scalar and return a string. + axis : {{0, 1, "index", "columns"}} + The headers over which to apply the function. + level : int, str, list, optional + If index is MultiIndex the level(s) over which to apply the function. + **kwargs : dict + Pass along to ``func``. + + Returns + ------- + Styler + """ + return self.map_index(func, axis, level, **kwargs) + + def _map(self, func: Callable, subset: Subset | None = None, **kwargs) -> Styler: + func = partial(func, **kwargs) # map doesn't take kwargs? if subset is None: subset = IndexSlice[:] subset = non_reducing_slice(subset) @@ -1943,9 +1975,7 @@ def _applymap( return self @Substitution(subset=subset_args) - def applymap( - self, func: Callable, subset: Subset | None = None, **kwargs - ) -> Styler: + def map(self, func: Callable, subset: Subset | None = None, **kwargs) -> Styler: """ Apply a CSS-styling function elementwise. @@ -1965,7 +1995,7 @@ def applymap( See Also -------- - Styler.applymap_index: Apply a CSS-styling function to headers elementwise. + Styler.map_index: Apply a CSS-styling function to headers elementwise. Styler.apply_index: Apply a CSS-styling function to headers level-wise. Styler.apply: Apply a CSS-styling function column-wise, row-wise, or table-wise. @@ -1980,30 +2010,55 @@ def applymap( >>> def color_negative(v, color): ... return f"color: {color};" if v < 0 else None >>> df = pd.DataFrame(np.random.randn(5, 2), columns=["A", "B"]) - >>> df.style.applymap(color_negative, color='red') # doctest: +SKIP + >>> df.style.map(color_negative, color='red') # doctest: +SKIP Using ``subset`` to restrict application to a single column or multiple columns - >>> df.style.applymap(color_negative, color='red', subset="A") + >>> df.style.map(color_negative, color='red', subset="A") ... # doctest: +SKIP - >>> df.style.applymap(color_negative, color='red', subset=["A", "B"]) + >>> df.style.map(color_negative, color='red', subset=["A", "B"]) ... # doctest: +SKIP Using a 2d input to ``subset`` to select rows in addition to columns - >>> df.style.applymap(color_negative, color='red', + >>> df.style.map(color_negative, color='red', ... subset=([0,1,2], slice(None))) # doctest: +SKIP - >>> df.style.applymap(color_negative, color='red', subset=(slice(0,5,2), "A")) + >>> df.style.map(color_negative, color='red', subset=(slice(0,5,2), "A")) ... # doctest: +SKIP See `Table Visualization <../../user_guide/style.ipynb>`_ user guide for more details. """ self._todo.append( - (lambda instance: getattr(instance, "_applymap"), (func, subset), kwargs) + (lambda instance: getattr(instance, "_map"), (func, subset), kwargs) ) return self + @Substitution(subset=subset_args) + def applymap( + self, func: Callable, subset: Subset | None = None, **kwargs + ) -> Styler: + """ + Apply a CSS-styling function elementwise. + + .. deprecated:: 2.1.0 + + Styler.applymap_index has been deprecated. Use Styler.map_index instead. + + Parameters + ---------- + func : function + ``func`` should take a scalar and return a string. + %(subset)s + **kwargs : dict + Pass along to ``func``. + + Returns + ------- + Styler + """ + return self.map(func, subset, **kwargs) + def set_table_attributes(self, attributes: str) -> Styler: """ Set the table attributes added to the ```` HTML element. From 1513c275ca1f2960b6e9c3aea265acbcef449b8a Mon Sep 17 00:00:00 2001 From: "JHM Darbyshire (iMac)" Date: Mon, 17 Apr 2023 20:24:42 +0200 Subject: [PATCH 2/7] update tests to new names with deprecation warnings --- doc/source/reference/style.rst | 4 +- pandas/io/formats/style.py | 38 ++++++++++++------- pandas/io/formats/style_render.py | 4 +- pandas/tests/io/formats/style/test_html.py | 26 ++++++------- .../tests/io/formats/style/test_non_unique.py | 6 +-- pandas/tests/io/formats/style/test_style.py | 32 ++++++++-------- .../tests/io/formats/style/test_to_latex.py | 12 +++--- 7 files changed, 66 insertions(+), 56 deletions(-) diff --git a/doc/source/reference/style.rst b/doc/source/reference/style.rst index 5144f12fa373a..2256876c93e01 100644 --- a/doc/source/reference/style.rst +++ b/doc/source/reference/style.rst @@ -36,9 +36,9 @@ Style application :toctree: api/ Styler.apply - Styler.applymap + Styler.map Styler.apply_index - Styler.applymap_index + Styler.map_index Styler.format Styler.format_index Styler.relabel_index diff --git a/pandas/io/formats/style.py b/pandas/io/formats/style.py index 33951f3570507..cc98ac14eb92b 100644 --- a/pandas/io/formats/style.py +++ b/pandas/io/formats/style.py @@ -16,6 +16,7 @@ Sequence, overload, ) +import warnings import numpy as np @@ -26,6 +27,7 @@ Substitution, doc, ) +from pandas.util._exceptions import find_stack_level import pandas as pd from pandas import ( @@ -205,7 +207,7 @@ class Styler(StylerRenderer): Notes ----- Most styling will be done by passing style functions into - ``Styler.apply`` or ``Styler.applymap``. Style functions should + ``Styler.apply`` or ``Styler.map``. Style functions should return values with strings containing CSS ``'attr: value'`` that will be applied to the indicated cells. @@ -305,8 +307,8 @@ def concat(self, other: Styler) -> Styler: For example adding a sub total row, or displaying metrics such as means, variance or counts. - Styles that are applied using the ``apply``, ``applymap``, ``apply_index`` - and ``applymap_index``, and formatting applied with ``format`` and + Styles that are applied using the ``apply``, ``map``, ``apply_index`` + and ``map_index``, and formatting applied with ``format`` and ``format_index`` will be preserved. .. warning:: @@ -353,7 +355,7 @@ def concat(self, other: Styler) -> Styler: >>> other = (descriptors.style ... .highlight_max(axis=1, subset=(["Total", "Average"], slice(None))) ... .format(subset=("Average", slice(None)), precision=2, decimal=",") - ... .applymap(lambda v: "font-weight: bold;")) + ... .map(lambda v: "font-weight: bold;")) >>> styler = (df.style ... .highlight_max(color="salmon") ... .set_table_styles([{"selector": ".foot_row0", @@ -990,7 +992,7 @@ def to_latex( ... else: color = "#ffdd33" ... return f"color: {color}; font-weight: bold;" >>> (styler.background_gradient(cmap="inferno", subset="Equity", vmin=0, vmax=1) - ... .applymap(rating_color, subset="Rating")) # doctest: +SKIP + ... .map(rating_color, subset="Rating")) # doctest: +SKIP All the above styles will work with HTML (see below) and LaTeX upon conversion: @@ -1002,7 +1004,7 @@ def to_latex( as well as `--rwrap` to ensure this is formatted correctly and not ignored upon conversion. - >>> styler.applymap_index( + >>> styler.map_index( ... lambda v: "rotatebox:{45}--rwrap--latex;", level=2, axis=1 ... ) # doctest: +SKIP @@ -1513,7 +1515,7 @@ def _update_ctx(self, attrs: DataFrame) -> None: """ if not self.index.is_unique or not self.columns.is_unique: raise KeyError( - "`Styler.apply` and `.applymap` are not compatible " + "`Styler.apply` and `.map` are not compatible " "with non-unique index or columns." ) @@ -1744,9 +1746,9 @@ def apply( See Also -------- - Styler.applymap_index: Apply a CSS-styling function to headers elementwise. + Styler.map_index: Apply a CSS-styling function to headers elementwise. Styler.apply_index: Apply a CSS-styling function to headers level-wise. - Styler.applymap: Apply a CSS-styling function elementwise. + Styler.map: Apply a CSS-styling function elementwise. Notes ----- @@ -1963,6 +1965,11 @@ def applymap_index( ------- Styler """ + warnings.warn( + "Styler.applymap_index has been deprecated. Use Styler.map_index instead.", + FutureWarning, + stacklevel=find_stack_level(), + ) return self.map_index(func, axis, level, **kwargs) def _map(self, func: Callable, subset: Subset | None = None, **kwargs) -> Styler: @@ -2057,6 +2064,11 @@ def applymap( ------- Styler """ + warnings.warn( + "Styler.applymap has been deprecated. Use Styler.map instead.", + FutureWarning, + stacklevel=find_stack_level(), + ) return self.map(func, subset, **kwargs) def set_table_attributes(self, attributes: str) -> Styler: @@ -2112,7 +2124,7 @@ def export(self) -> dict[str, Any]: The following items are exported since they are not generally data dependent: - - Styling functions added by the ``apply`` and ``applymap`` + - Styling functions added by the ``apply`` and ``map`` - Whether axes and names are hidden from the display, if unambiguous. - Table attributes - Table styles @@ -2158,7 +2170,7 @@ def use(self, styles: dict[str, Any]) -> Styler: styles : dict(str, Any) List of attributes to add to Styler. Dict keys should contain only: - "apply": list of styler functions, typically added with ``apply`` or - ``applymap``. + ``map``. - "table_attributes": HTML attributes, typically added with ``set_table_attributes``. - "table_styles": CSS selectors and properties, typically added with @@ -2947,7 +2959,7 @@ def set_properties(self, subset: Subset | None = None, **kwargs) -> Styler: Notes ----- - This is a convenience methods which wraps the :meth:`Styler.applymap` calling a + This is a convenience methods which wraps the :meth:`Styler.map` calling a function returning the CSS-properties independently of the data. Examples @@ -2960,7 +2972,7 @@ def set_properties(self, subset: Subset | None = None, **kwargs) -> Styler: more details. """ values = "".join([f"{p}: {v};" for p, v in kwargs.items()]) - return self.applymap(lambda x: values, subset=subset) + return self.map(lambda x: values, subset=subset) @Substitution(subset=subset_args) def bar( # pylint: disable=disallowed-name diff --git a/pandas/io/formats/style_render.py b/pandas/io/formats/style_render.py index 3a3b784c9d4d7..a370ca7421568 100644 --- a/pandas/io/formats/style_render.py +++ b/pandas/io/formats/style_render.py @@ -247,7 +247,7 @@ def _compute(self): Execute the style functions built up in `self._todo`. Relies on the conventions that all style functions go through - .apply or .applymap. The append styles to apply as tuples of + .apply or .map. The append styles to apply as tuples of (application method, *args, **kwargs) """ @@ -1168,7 +1168,7 @@ def format( >>> df = pd.DataFrame({"A": [1, 0, -1]}) >>> pseudo_css = "number-format: 0§[Red](0)§-§@;" >>> filename = "formatted_file.xlsx" - >>> df.style.applymap(lambda v: pseudo_css).to_excel(filename) # doctest: +SKIP + >>> df.style.map(lambda v: pseudo_css).to_excel(filename) # doctest: +SKIP .. figure:: ../../_static/style/format_excel_css.png """ diff --git a/pandas/tests/io/formats/style/test_html.py b/pandas/tests/io/formats/style/test_html.py index 1867260fbc4b4..67f7e12fcc3c2 100644 --- a/pandas/tests/io/formats/style/test_html.py +++ b/pandas/tests/io/formats/style/test_html.py @@ -85,11 +85,9 @@ def test_exclude_styles(styler): def test_w3_html_format(styler): - styler.set_uuid("").set_table_styles( - [{"selector": "th", "props": "att2:v2;"}] - ).applymap(lambda x: "att1:v1;").set_table_attributes( - 'class="my-cls1" style="attr3:v3;"' - ).set_td_classes( + styler.set_uuid("").set_table_styles([{"selector": "th", "props": "att2:v2;"}]).map( + lambda x: "att1:v1;" + ).set_table_attributes('class="my-cls1" style="attr3:v3;"').set_td_classes( DataFrame(["my-cls2"], index=["a"], columns=["A"]) ).format( "{:.1f}" @@ -428,14 +426,14 @@ def test_sparse_options(sparse_index, sparse_columns): @pytest.mark.parametrize("index", [True, False]) @pytest.mark.parametrize("columns", [True, False]) -def test_applymap_header_cell_ids(styler, index, columns): +def test_map_header_cell_ids(styler, index, columns): # GH 41893 func = lambda v: "attr: val;" styler.uuid, styler.cell_ids = "", False if index: - styler.applymap_index(func, axis="index") + styler.map_index(func, axis="index") if columns: - styler.applymap_index(func, axis="columns") + styler.map_index(func, axis="columns") result = styler.to_html() @@ -493,9 +491,9 @@ def test_replaced_css_class_names(): styler_mi.index.names = ["n1", "n2"] styler_mi.hide(styler_mi.index[1:], axis=0) styler_mi.hide(styler_mi.columns[1:], axis=1) - styler_mi.applymap_index(lambda v: "color: red;", axis=0) - styler_mi.applymap_index(lambda v: "color: green;", axis=1) - styler_mi.applymap(lambda v: "color: blue;") + styler_mi.map_index(lambda v: "color: red;", axis=0) + styler_mi.map_index(lambda v: "color: green;", axis=1) + styler_mi.map(lambda v: "color: blue;") expected = dedent( """\