@@ -171,6 +171,8 @@ def __init__(
171171 self .cell_ids = cell_ids
172172 self .na_rep = na_rep
173173
174+ self .cell_context : Dict [str , Any ] = {}
175+
174176 # display_funcs maps (row, col) -> formatting function
175177
176178 def default_display_func (x ):
@@ -262,7 +264,7 @@ def format_attr(pair):
262264 idx_lengths = _get_level_lengths (self .index )
263265 col_lengths = _get_level_lengths (self .columns , hidden_columns )
264266
265- cell_context = dict ()
267+ cell_context = self . cell_context
266268
267269 n_rlvls = self .data .index .nlevels
268270 n_clvls = self .data .columns .nlevels
@@ -499,6 +501,70 @@ def format(self, formatter, subset=None, na_rep: Optional[str] = None) -> "Style
499501 self ._display_funcs [(i , j )] = formatter
500502 return self
501503
504+ def set_td_classes (self , classes : DataFrame ) -> "Styler" :
505+ """
506+ Add string based CSS class names to data cells that will appear within the
507+ `Styler` HTML result. These classes are added within specified `<td>` elements.
508+
509+ Parameters
510+ ----------
511+ classes : DataFrame
512+ DataFrame containing strings that will be translated to CSS classes,
513+ mapped by identical column and index values that must exist on the
514+ underlying `Styler` data. None, NaN values, and empty strings will
515+ be ignored and not affect the rendered HTML.
516+
517+ Returns
518+ -------
519+ self : Styler
520+
521+ Examples
522+ --------
523+ >>> df = pd.DataFrame(data=[[1, 2, 3], [4, 5, 6]], columns=["A", "B", "C"])
524+ >>> classes = pd.DataFrame([
525+ ... ["min-val red", "", "blue"],
526+ ... ["red", None, "blue max-val"]
527+ ... ], index=df.index, columns=df.columns)
528+ >>> df.style.set_td_classes(classes)
529+
530+ Using `MultiIndex` columns and a `classes` `DataFrame` as a subset of the
531+ underlying,
532+
533+ >>> df = pd.DataFrame([[1,2],[3,4]], index=["a", "b"],
534+ ... columns=[["level0", "level0"], ["level1a", "level1b"]])
535+ >>> classes = pd.DataFrame(["min-val"], index=["a"],
536+ ... columns=[["level0"],["level1a"]])
537+ >>> df.style.set_td_classes(classes)
538+
539+ Form of the output with new additional css classes,
540+
541+ >>> df = pd.DataFrame([[1]])
542+ >>> css = pd.DataFrame(["other-class"])
543+ >>> s = Styler(df, uuid="_", cell_ids=False).set_td_classes(css)
544+ >>> s.hide_index().render()
545+ '<style type="text/css" ></style>'
546+ '<table id="T__" >'
547+ ' <thead>'
548+ ' <tr><th class="col_heading level0 col0" >0</th></tr>'
549+ ' </thead>'
550+ ' <tbody>'
551+ ' <tr><td class="data row0 col0 other-class" >1</td></tr>'
552+ ' </tbody>'
553+ '</table>'
554+
555+ """
556+ classes = classes .reindex_like (self .data )
557+
558+ mask = (classes .isna ()) | (classes .eq ("" ))
559+ self .cell_context ["data" ] = {
560+ r : {c : [str (classes .iloc [r , c ])]}
561+ for r , rn in enumerate (classes .index )
562+ for c , cn in enumerate (classes .columns )
563+ if not mask .iloc [r , c ]
564+ }
565+
566+ return self
567+
502568 def render (self , ** kwargs ) -> str :
503569 """
504570 Render the built up styles to HTML.
@@ -609,6 +675,7 @@ def clear(self) -> None:
609675 Returns None.
610676 """
611677 self .ctx .clear ()
678+ self .cell_context = {}
612679 self ._todo = []
613680
614681 def _compute (self ):
0 commit comments