Skip to content

ENH: allow concat of Styler objects #46105

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 48 commits into from
Feb 27, 2022
Merged
Show file tree
Hide file tree
Changes from 20 commits
Commits
Show all changes
48 commits
Select commit Hold shift + click to select a range
4cfb671
skeleton
attack68 Feb 19, 2022
ba3d421
html template
attack68 Feb 19, 2022
2f36cef
test internals
attack68 Feb 19, 2022
3927adc
additional tests
attack68 Feb 19, 2022
8d6dabc
additional tests
attack68 Feb 19, 2022
56262b8
additional tests
attack68 Feb 19, 2022
aeeca3b
additional tests
attack68 Feb 19, 2022
f8cf8af
additional tests
attack68 Feb 19, 2022
7703343
additional tests
attack68 Feb 19, 2022
5d70293
errors testing
attack68 Feb 19, 2022
6811f4b
errors testing
attack68 Feb 19, 2022
409fad2
doc edits
attack68 Feb 20, 2022
d516b2f
LaTeX footer
attack68 Feb 20, 2022
6890e56
to_string mods, and tests
attack68 Feb 20, 2022
7281a9c
doc edits
attack68 Feb 20, 2022
e6fbf53
valueerror test
attack68 Feb 21, 2022
88db947
REMOVE CUSTOM FORMATTING
attack68 Feb 21, 2022
8c8ae96
doc edits
attack68 Feb 21, 2022
5511e80
doc edits
attack68 Feb 21, 2022
5400614
test moved
attack68 Feb 21, 2022
28bc86b
Merge remote-tracking branch 'upstream/main' into styler_footer
attack68 Feb 22, 2022
f158eeb
concatenate instead
attack68 Feb 22, 2022
bf06ce1
removing redundant code
attack68 Feb 22, 2022
af287e2
removing redundant code
attack68 Feb 22, 2022
aa02e86
removing redundant code
attack68 Feb 22, 2022
0ae6b53
removing redundant code
attack68 Feb 22, 2022
7ebddd0
removing redundant code
attack68 Feb 22, 2022
5a7ccc7
doc edits
attack68 Feb 22, 2022
bba6077
doc edits
attack68 Feb 22, 2022
1032336
doc edits
attack68 Feb 22, 2022
394b9e0
edit tests
attack68 Feb 22, 2022
cf42933
edit tests
attack68 Feb 22, 2022
dfcdf6b
general render method
attack68 Feb 23, 2022
64cf7bc
doc warnings
attack68 Feb 23, 2022
ad23748
doc warnings
attack68 Feb 23, 2022
f92c54c
revert merge
attack68 Feb 23, 2022
5aeb8b8
html test
attack68 Feb 23, 2022
1417e7e
Merge remote-tracking branch 'upstream/main' into styler_footer
attack68 Feb 23, 2022
70184fa
doc test fix
attack68 Feb 23, 2022
0c107d2
edit docs
attack68 Feb 23, 2022
3b1cac3
Merge remote-tracking branch 'upstream/main' into styler_footer
attack68 Feb 24, 2022
5b44e92
fix typing
attack68 Feb 25, 2022
a21beef
reorder calculation for recursion
attack68 Feb 25, 2022
5debdf6
allow working chained multiple concatenation
attack68 Feb 25, 2022
eccf6db
fix test with chaining
attack68 Feb 25, 2022
e2a1bbd
Merge remote-tracking branch 'upstream/main' into styler_footer
attack68 Feb 26, 2022
f2701a2
mypy fix
attack68 Feb 26, 2022
534d5c0
mypy fix
attack68 Feb 27, 2022
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Binary file added doc/source/_static/style/footer_hypothesis.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added doc/source/_static/style/footer_simple.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
1 change: 1 addition & 0 deletions doc/source/reference/style.rst
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ Style application
Styler.format
Styler.format_index
Styler.hide
Styler.set_footer
Styler.set_td_classes
Styler.set_table_styles
Styler.set_table_attributes
Expand Down
1 change: 1 addition & 0 deletions doc/source/whatsnew/v1.5.0.rst
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ Styler

- New method :meth:`.Styler.to_string` for alternative customisable output methods (:issue:`44502`)
- Added the ability to render ``border`` and ``border-{side}`` CSS properties in Excel (:issue:`42276`)
- Added a new method :meth:`.Styler.set_footer` which allows adding customised footer rows to explore and make calculations on the data, e.g. totals and counts etc. (:issue:`43875`)

.. _whatsnew_150.enhancements.enhancement2:

Expand Down
97 changes: 95 additions & 2 deletions pandas/io/formats/style.py
Original file line number Diff line number Diff line change
Expand Up @@ -1435,6 +1435,7 @@ def _copy(self, deepcopy: bool = False) -> Styler:
]
deep = [ # nested lists or dicts
"css",
"descriptors",
"_display_funcs",
"_display_funcs_index",
"_display_funcs_columns",
Expand Down Expand Up @@ -1977,6 +1978,9 @@ def export(self) -> dict[str, Any]:

Can be applied to a second Styler with ``Styler.use``.

.. versionchanged:: 1.5.0
Adds ``descriptors`` to the exported items for use with ``set_footer``.

Returns
-------
styles : dict
Expand All @@ -1995,9 +1999,10 @@ 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``
- Whether axes and names are hidden from the display, if unambiguous.
- Whether axes and names are hidden from the display, if unambiguous
- Table attributes
- Table styles
- Descriptors, i.e. from ``set_footer``

The following attributes are considered data dependent and therefore not
exported:
Expand Down Expand Up @@ -2027,6 +2032,7 @@ def export(self) -> dict[str, Any]:
"hide_index_names": self.hide_index_names,
"hide_column_names": self.hide_column_names,
"css": copy.copy(self.css),
"descriptors": copy.copy(self.descriptors),
}

def use(self, styles: dict[str, Any]) -> Styler:
Expand All @@ -2035,6 +2041,9 @@ def use(self, styles: dict[str, Any]) -> Styler:

Possibly uses styles from ``Styler.export``.

.. versionchanged:: 1.5.0
Adds ``descriptors`` to the used items for use with ``set_footer``.

Parameters
----------
styles : dict(str, Any)
Expand All @@ -2052,6 +2061,7 @@ def use(self, styles: dict[str, Any]) -> Styler:
- "hide_index_names": whether index names are hidden.
- "hide_column_names": whether column header names are hidden.
- "css": the css class names used.
- "descriptors": list of descriptors, typically added with ``set_footer``.

Returns
-------
Expand Down Expand Up @@ -2094,6 +2104,12 @@ def use(self, styles: dict[str, Any]) -> Styler:
self.hide_column_names = styles.get("hide_column_names", False)
if styles.get("css"):
self.css = styles.get("css") # type: ignore[assignment]
if styles.get("descriptors") and styles["descriptors"]["methods"]:
self.set_footer(
func=styles["descriptors"]["methods"],
alias=styles["descriptors"]["names"],
errors=styles["descriptors"]["errors"],
)
return self

def set_uuid(self, uuid: str) -> Styler:
Expand Down Expand Up @@ -2352,7 +2368,10 @@ def set_table_styles(
"row_trim": "row_trim",
"level": "level",
"data": "data",
"blank": "blank}
"blank": "blank",
"descriptor": "descriptor",
"descriptor_name": "descriptor_name",
"descriptor_value": "descriptor_value"}

Examples
--------
Expand Down Expand Up @@ -2423,6 +2442,80 @@ def set_table_styles(
self.table_styles = table_styles
return self

def set_footer(
self,
func: Sequence[str | Callable] | None = None,
alias: Sequence[str] | None = None,
errors: str = "ignore",
) -> Styler:
"""
Add footer-level calculations to the output which describes the data.

.. versionadded:: 1.5.0

Parameters
----------
func : list-like of str or callable
If a string is given must be a valid Series method, e.g. "mean" invokes
Series.mean().
If a callable is given must accept a Series and return a scalar.
alias : list-like of str, optional
Aliases to use for the function names. Must have length equal to ``func``.
errors : {"ignore", "warn", "raise"}
If errors, will be ignored or warned returning ``NA``, or raise.

Returns
-------
self : Styler

Notes
-----
These metrics are calculated at render time and can therefore be exported
and used on other general Styler objects.

Footers are applied to Styler output formats including ``to_html``,
``to_latex`` and ``to_string``, but not, currently, ``to_excel``.

Examples
--------
A common use case is adding totals rows for descriptive tables, with ``func``.

>>> df = DataFrame([[4, 6], [1, 9], [3, 4], [5, 5], [9,6]],
... columns=["Mike", "Jim"],
... index=["Mon", "Tue", "Wed", "Thurs", "Fri"])
>>> styler = df.style.set_footer(["sum"]) # doctest: +SKIP

.. figure:: ../../_static/style/footer_simple.png

User defined functions and an ``alias`` can also be used, which is useful for
displaying metrics such as dtypes, missing value counts, or unique value
counts etc.

>>> def reject_h0(s):
... count = (s > 0.8).sum()
... return "Reject" if count > 3 else "Accept"
>>> df = DataFrame({
... "Machine 1": np.random.rand(10),
... "Machine 2": np.random.rand(10),
... "Machine 3": np.random.rand(10),
... })
>>> df.style.highlight_between(left=0.8, props="color: red;")
... .set_footer(func=[reject_h0],
... alias=["Hypothesis Test:"]) # doctest: +SKIP

.. figure:: ../../_static/style/footer_hypothesis.png
"""
if func is not None:
if alias is not None and len(alias) != len(func):
raise ValueError("``alias`` must have same length as ``func``")

self.descriptors = {
"methods": func,
"names": alias,
"errors": errors,
}
return self

def set_na_rep(self, na_rep: str) -> StylerRenderer:
"""
Set the missing data representation on a ``Styler``.
Expand Down
Loading