@@ -140,9 +140,15 @@ def __init__(
140
140
self ._display_funcs_index : DefaultDict [ # maps (row, level) -> format func
141
141
tuple [int , int ], Callable [[Any ], str ]
142
142
] = defaultdict (lambda : partial (_default_formatter , precision = precision ))
143
+ self ._display_funcs_index_names : DefaultDict [ # maps index level -> format func
144
+ tuple [int , int ], Callable [[Any ], str ]
145
+ ] = defaultdict (lambda : partial (_default_formatter , precision = precision ))
143
146
self ._display_funcs_columns : DefaultDict [ # maps (level, col) -> format func
144
147
tuple [int , int ], Callable [[Any ], str ]
145
148
] = defaultdict (lambda : partial (_default_formatter , precision = precision ))
149
+ self ._display_funcs_column_names : DefaultDict [ # maps col level -> format func
150
+ tuple [int , int ], Callable [[Any ], str ]
151
+ ] = defaultdict (lambda : partial (_default_formatter , precision = precision ))
146
152
147
153
def _render (
148
154
self ,
@@ -460,6 +466,12 @@ def _generate_col_header_row(
460
466
] * (self .index .nlevels - sum (self .hide_index_ ) - 1 )
461
467
462
468
name = self .data .columns .names [r ]
469
+
470
+ is_display = name is not None and not self .hide_column_names
471
+ value = name if is_display else self .css ["blank_value" ]
472
+ display_value = (
473
+ self ._display_funcs_column_names [r ](value ) if is_display else None
474
+ )
463
475
column_name = [
464
476
_element (
465
477
"th" ,
@@ -468,10 +480,9 @@ def _generate_col_header_row(
468
480
if name is None
469
481
else f"{ self .css ['index_name' ]} { self .css ['level' ]} { r } "
470
482
),
471
- name
472
- if (name is not None and not self .hide_column_names )
473
- else self .css ["blank_value" ],
483
+ value ,
474
484
not all (self .hide_index_ ),
485
+ display_value = display_value ,
475
486
)
476
487
]
477
488
@@ -553,6 +564,9 @@ def _generate_index_names_row(
553
564
f"{ self .css ['index_name' ]} { self .css ['level' ]} { c } " ,
554
565
self .css ["blank_value" ] if name is None else name ,
555
566
not self .hide_index_ [c ],
567
+ display_value = (
568
+ None if name is None else self ._display_funcs_index_names [c ](name )
569
+ ),
556
570
)
557
571
for c , name in enumerate (self .data .index .names )
558
572
]
@@ -1560,6 +1574,139 @@ def alias_(x, value):
1560
1574
1561
1575
return self
1562
1576
1577
+ def format_names (
1578
+ self ,
1579
+ formatter : ExtFormatter | None = None ,
1580
+ axis : Axis = 0 ,
1581
+ level : Level | list [Level ] | None = None ,
1582
+ na_rep : str | None = None ,
1583
+ precision : int | None = None ,
1584
+ decimal : str = "." ,
1585
+ thousands : str | None = None ,
1586
+ escape : str | None = None ,
1587
+ hyperlinks : str | None = None ,
1588
+ ) -> StylerRenderer :
1589
+ r"""
1590
+ Format the text display value of index names or column names.
1591
+
1592
+ .. versionadded:: TODO
1593
+
1594
+ Parameters
1595
+ ----------
1596
+ formatter : str, callable, dict or None
1597
+ Object to define how values are displayed. See notes.
1598
+ axis : {0, "index", 1, "columns"}
1599
+ Whether to apply the formatter to the index or column headers.
1600
+ level : int, str, list
1601
+ The level(s) over which to apply the generic formatter.
1602
+ na_rep : str, optional
1603
+ Representation for missing values.
1604
+ If ``na_rep`` is None, no special formatting is applied.
1605
+ precision : int, optional
1606
+ Floating point precision to use for display purposes, if not determined by
1607
+ the specified ``formatter``.
1608
+ decimal : str, default "."
1609
+ Character used as decimal separator for floats, complex and integers.
1610
+ thousands : str, optional, default None
1611
+ Character used as thousands separator for floats, complex and integers.
1612
+ escape : str, optional
1613
+ Use 'html' to replace the characters ``&``, ``<``, ``>``, ``'``, and ``"``
1614
+ in cell display string with HTML-safe sequences.
1615
+ Use 'latex' to replace the characters ``&``, ``%``, ``$``, ``#``, ``_``,
1616
+ ``{``, ``}``, ``~``, ``^``, and ``\`` in the cell display string with
1617
+ LaTeX-safe sequences.
1618
+ Escaping is done before ``formatter``.
1619
+ hyperlinks : {"html", "latex"}, optional
1620
+ Convert string patterns containing https://, http://, ftp:// or www. to
1621
+ HTML <a> tags as clickable URL hyperlinks if "html", or LaTeX \href
1622
+ commands if "latex".
1623
+
1624
+ Returns
1625
+ -------
1626
+ Styler
1627
+
1628
+ See Also
1629
+ --------
1630
+ Styler.format_index: Format the text display value of index labels
1631
+ or column headers.
1632
+
1633
+ Notes
1634
+ -----
1635
+ This method assigns a formatting function, ``formatter``, to each level label
1636
+ in the DataFrame's index or column headers. If ``formatter`` is ``None``,
1637
+ then the default formatter is used.
1638
+ If a callable then that function should take a label value as input and return
1639
+ a displayable representation, such as a string. If ``formatter`` is
1640
+ given as a string this is assumed to be a valid Python format specification
1641
+ and is wrapped to a callable as ``string.format(x)``. If a ``dict`` is given,
1642
+ keys should correspond to MultiIndex level numbers or names, and values should
1643
+ be string or callable, as above.
1644
+
1645
+ The default formatter currently expresses floats and complex numbers with the
1646
+ pandas display precision unless using the ``precision`` argument here. The
1647
+ default formatter does not adjust the representation of missing values unless
1648
+ the ``na_rep`` argument is used.
1649
+
1650
+ The ``level`` argument defines which levels of a MultiIndex to apply the
1651
+ method to. If the ``formatter`` argument is given in dict form but does
1652
+ not include all levels within the level argument then these unspecified levels
1653
+ will have the default formatter applied. Any levels in the formatter dict
1654
+ specifically excluded from the level argument will be ignored.
1655
+
1656
+ When using a ``formatter`` string the dtypes must be compatible, otherwise a
1657
+ `ValueError` will be raised.
1658
+
1659
+ .. warning::
1660
+ `Styler.format_index` is ignored when using the output format
1661
+ `Styler.to_excel`, since Excel and Python have inherrently different
1662
+ formatting structures.
1663
+ However, it is possible to use the `number-format` pseudo CSS attribute
1664
+ to force Excel permissible formatting. See documentation for `Styler.format`.
1665
+ """
1666
+ axis = self .data ._get_axis_number (axis )
1667
+ if axis == 0 :
1668
+ display_funcs_ , obj = self ._display_funcs_index_names , self .index
1669
+ else :
1670
+ display_funcs_ , obj = self ._display_funcs_column_names , self .columns
1671
+ levels_ = refactor_levels (level , obj )
1672
+
1673
+ if all (
1674
+ (
1675
+ formatter is None ,
1676
+ level is None ,
1677
+ precision is None ,
1678
+ decimal == "." ,
1679
+ thousands is None ,
1680
+ na_rep is None ,
1681
+ escape is None ,
1682
+ hyperlinks is None ,
1683
+ )
1684
+ ):
1685
+ display_funcs_ .clear ()
1686
+ return self # clear the formatter / revert to default and avoid looping
1687
+
1688
+ if not isinstance (formatter , dict ):
1689
+ formatter = {level : formatter for level in levels_ }
1690
+ else :
1691
+ formatter = {
1692
+ obj ._get_level_number (level ): formatter_
1693
+ for level , formatter_ in formatter .items ()
1694
+ }
1695
+
1696
+ for lvl in levels_ :
1697
+ format_func = _maybe_wrap_formatter (
1698
+ formatter .get (lvl ),
1699
+ na_rep = na_rep ,
1700
+ precision = precision ,
1701
+ decimal = decimal ,
1702
+ thousands = thousands ,
1703
+ escape = escape ,
1704
+ hyperlinks = hyperlinks ,
1705
+ )
1706
+ display_funcs_ [lvl ] = format_func
1707
+
1708
+ return self
1709
+
1563
1710
1564
1711
def _element (
1565
1712
html_element : str ,
@@ -1571,7 +1718,7 @@ def _element(
1571
1718
"""
1572
1719
Template to return container with information for a <td></td> or <th></th> element.
1573
1720
"""
1574
- if "display_value" not in kwargs :
1721
+ if "display_value" not in kwargs or kwargs [ "display_value" ] is None :
1575
1722
kwargs ["display_value" ] = value
1576
1723
return {
1577
1724
"type" : html_element ,
0 commit comments