diff --git a/doc/source/reference/style.rst b/doc/source/reference/style.rst index 6c6b24b4b9136..90ec5a2283f1e 100644 --- a/doc/source/reference/style.rst +++ b/doc/source/reference/style.rst @@ -39,7 +39,6 @@ Style application Styler.set_table_styles Styler.set_table_attributes Styler.set_tooltips - Styler.set_tooltips_class Styler.set_caption Styler.set_properties Styler.set_uuid diff --git a/doc/source/whatsnew/v1.3.0.rst b/doc/source/whatsnew/v1.3.0.rst index fb8eecdaa275e..dcc1d7b6d7f97 100644 --- a/doc/source/whatsnew/v1.3.0.rst +++ b/doc/source/whatsnew/v1.3.0.rst @@ -131,8 +131,8 @@ Other enhancements - Disallow :class:`DataFrame` indexer for ``iloc`` for :meth:`Series.__getitem__` and :meth:`DataFrame.__getitem__`, (:issue:`39004`) - :meth:`Series.apply` can now accept list-like or dictionary-like arguments that aren't lists or dictionaries, e.g. ``ser.apply(np.array(["sum", "mean"]))``, which was already the case for :meth:`DataFrame.apply` (:issue:`39140`) - :meth:`DataFrame.plot.scatter` can now accept a categorical column as the argument to ``c`` (:issue:`12380`, :issue:`31357`) -- :meth:`.Styler.set_tooltips` allows on hover tooltips to be added to styled HTML dataframes (:issue:`35643`, :issue:`21266`, :issue:`39317`, :issue:`39708`) -- :meth:`.Styler.set_tooltips_class` and :meth:`.Styler.set_table_styles` amended to optionally allow certain css-string input arguments (:issue:`39564`) +- :meth:`.Styler.set_tooltips` allows on hover tooltips to be added to styled HTML dataframes (:issue:`35643`, :issue:`21266`, :issue:`39317`, :issue:`39708`, :issue:`40284`) +- :meth:`.Styler.set_table_styles` amended to optionally allow certain css-string input arguments (:issue:`39564`) - :meth:`.Styler.apply` now more consistently accepts ndarray function returns, i.e. in all cases for ``axis`` is ``0, 1 or None`` (:issue:`39359`) - :meth:`.Styler.apply` and :meth:`.Styler.applymap` now raise errors if wrong format CSS is passed on render (:issue:`39660`) - Builtin highlighting methods in :class:`Styler` have a more consistent signature and css customisability (:issue:`40242`) diff --git a/pandas/io/formats/style.py b/pandas/io/formats/style.py index 619b71611674f..af8c4821df755 100644 --- a/pandas/io/formats/style.py +++ b/pandas/io/formats/style.py @@ -209,20 +209,12 @@ def _repr_html_(self) -> str: """ return self.render() - def _init_tooltips(self): - """ - Checks parameters compatible with tooltips and creates instance if necessary - """ - if not self.cell_ids: - # tooltips not optimised for individual cell check. requires reasonable - # redesign and more extensive code for a feature that might be rarely used. - raise NotImplementedError( - "Tooltips can only render with 'cell_ids' is True." - ) - if self.tooltips is None: - self.tooltips = _Tooltips() - - def set_tooltips(self, ttips: DataFrame) -> Styler: + def set_tooltips( + self, + ttips: DataFrame, + props: Optional[CSSProperties] = None, + css_class: Optional[str] = None, + ) -> Styler: """ Add string based tooltips that will appear in the `Styler` HTML result. These tooltips are applicable only to`` elements. @@ -236,6 +228,13 @@ def set_tooltips(self, ttips: DataFrame) -> Styler: by identical column and index values that must exist on the underlying `Styler` data. None, NaN values, and empty strings will be ignored and not affect the rendered HTML. + props : list-like or str, optional + List of (attr, value) tuples or a valid CSS string. If ``None`` adopts + the internal default values described in notes. + css_class : str, optional + Name of the tooltip class used in CSS, should conform to HTML standards. + Only useful if integrating tooltips with external CSS. If ``None`` uses the + internal default value 'pd-t'. Returns ------- @@ -245,51 +244,7 @@ def set_tooltips(self, ttips: DataFrame) -> Styler: ----- Tooltips are created by adding `` to each data cell and then manipulating the table level CSS to attach pseudo hover and pseudo - after selectors to produce the required the results. For styling control - see `:meth:Styler.set_tooltips_class`. - Tooltips are not designed to be efficient, and can add large amounts of - additional HTML for larger tables, since they also require that `cell_ids` - is forced to `True`. - - Examples - -------- - >>> df = pd.DataFrame(data=[[0, 1], [2, 3]]) - >>> ttips = pd.DataFrame( - ... data=[["Min", ""], [np.nan, "Max"]], columns=df.columns, index=df.index - ... ) - >>> s = df.style.set_tooltips(ttips).render() - """ - self._init_tooltips() - assert self.tooltips is not None # mypy requiremen - self.tooltips.tt_data = ttips - return self - - def set_tooltips_class( - self, - name: Optional[str] = None, - properties: Optional[CSSProperties] = None, - ) -> Styler: - """ - Manually configure the name and/or properties of the class for - creating tooltips on hover. - - .. versionadded:: 1.3.0 - - Parameters - ---------- - name : str, default None - Name of the tooltip class used in CSS, should conform to HTML standards. - properties : list-like or str, default None - List of (attr, value) tuples or a valid CSS string; see example. - - Returns - ------- - self : Styler - - Notes - ----- - If arguments are `None` will not make any changes to the underlying ``Tooltips`` - existing values. + after selectors to produce the required the results. The default properties for the tooltip CSS class are: @@ -300,26 +255,47 @@ def set_tooltips_class( - color: white - transform: translate(-20px, -20px) - The property ('visibility', 'hidden') is a key prerequisite to the hover + The property 'visibility: hidden;' is a key prerequisite to the hover functionality, and should always be included in any manual properties - specification. + specification, using the ``props`` argument. + + Tooltips are not designed to be efficient, and can add large amounts of + additional HTML for larger tables, since they also require that ``cell_ids`` + is forced to `True`. Examples -------- - >>> df = pd.DataFrame(np.random.randn(10, 4)) - >>> df.style.set_tooltips_class(name='tt-add', properties=[ + Basic application + + >>> df = pd.DataFrame(data=[[0, 1], [2, 3]]) + >>> ttips = pd.DataFrame( + ... data=[["Min", ""], [np.nan, "Max"]], columns=df.columns, index=df.index + ... ) + >>> s = df.style.set_tooltips(ttips).render() + + Optionally controlling the tooltip visual display + + >>> df.style.set_tooltips(ttips, css_class='tt-add', props=[ ... ('visibility', 'hidden'), ... ('position', 'absolute'), ... ('z-index', 1)]) - >>> df.style.set_tooltips_class(name='tt-add', - ... properties='visibility:hidden; position:absolute; z-index:1;') - """ - self._init_tooltips() - assert self.tooltips is not None # mypy requirement - if properties: - self.tooltips.class_properties = properties - if name: - self.tooltips.class_name = name + >>> df.style.set_tooltips(ttips, css_class='tt-add', + ... props='visibility:hidden; position:absolute; z-index:1;') + """ + if not self.cell_ids: + # tooltips not optimised for individual cell check. requires reasonable + # redesign and more extensive code for a feature that might be rarely used. + raise NotImplementedError( + "Tooltips can only render with 'cell_ids' is True." + ) + if self.tooltips is None: # create a default instance if necessary + self.tooltips = _Tooltips() + self.tooltips.tt_data = ttips + if props: + self.tooltips.class_properties = props + if css_class: + self.tooltips.class_name = css_class + return self @doc( diff --git a/pandas/tests/io/formats/style/test_tooltip.py b/pandas/tests/io/formats/style/test_tooltip.py index 7aebb6fadc7b1..9539780287f15 100644 --- a/pandas/tests/io/formats/style/test_tooltip.py +++ b/pandas/tests/io/formats/style/test_tooltip.py @@ -73,7 +73,7 @@ def test_tooltip_reindex(self): 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() + s = Styler(df).render() # no set_tooltips() creates no assert '' in s assert '' not in s @@ -82,8 +82,11 @@ def test_tooltip_css_class(self): 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")]) + .set_tooltips( + DataFrame([["tooltip"]]), + css_class="other-class", + props=[("color", "green")], + ) .render() ) assert "#T__ .other-class {\n color: green;\n" in s @@ -92,8 +95,11 @@ def test_tooltip_css_class(self): # GH 39563 s = ( Styler(df, uuid_len=0) - .set_tooltips(DataFrame([["tooltip"]])) - .set_tooltips_class(name="other-class", properties="color:green;color:red;") + .set_tooltips( + DataFrame([["tooltip"]]), + css_class="other-class", + props="color:green;color:red;", + ) .render() ) assert "#T__ .other-class {\n color: green;\n color: red;\n}" in s