`` where `k` is the level in a MultiIndex
* Blank cells include ``blank``
* Data cells include ``data``
* Trimmed cells include ``col_trim`` or ``row_trim``.
Any, or all, or these classes can be renamed by using the ``css_class_names``
argument in ``Styler.set_table_styles``, giving a value such as
*{"row": "MY_ROW_CLASS", "col_trim": "", "row_trim": ""}*.
Examples
--------
>>> df = pd.DataFrame(
... [[1.0, 2.0, 3.0], [4, 5, 6]], index=["a", "b"], columns=["A", "B", "C"]
... )
>>> pd.io.formats.style.Styler(
... df, precision=2, caption="My table"
... ) # doctest: +SKIP
Please see:
`Table Visualization <../../user_guide/style.ipynb>`_ for more examples.
"""
def __init__(
self,
data: DataFrame | Series,
precision: int | None = None,
table_styles: CSSStyles | None = None,
uuid: str | None = None,
caption: str | tuple | list | None = None,
table_attributes: str | None = None,
cell_ids: bool = True,
na_rep: str | None = None,
uuid_len: int = 5,
decimal: str | None = None,
thousands: str | None = None,
escape: str | None = None,
formatter: ExtFormatter | None = None,
) -> None:
super().__init__(
data=data,
uuid=uuid,
uuid_len=uuid_len,
table_styles=table_styles,
table_attributes=table_attributes,
caption=caption,
cell_ids=cell_ids,
precision=precision,
)
# validate ordered args
thousands = thousands or get_option("styler.format.thousands")
decimal = decimal or get_option("styler.format.decimal")
na_rep = na_rep or get_option("styler.format.na_rep")
escape = escape or get_option("styler.format.escape")
formatter = formatter or get_option("styler.format.formatter")
# precision is handled by superclass as default for performance
self.format(
formatter=formatter,
precision=precision,
na_rep=na_rep,
escape=escape,
decimal=decimal,
thousands=thousands,
)
def concat(self, other: Styler) -> Styler:
"""
Append another Styler to combine the output into a single table.
Parameters
----------
other : Styler
The other Styler object which has already been styled and formatted. The
data for this Styler must have the same columns as the original, and the
number of index levels must also be the same to render correctly.
Returns
-------
Styler
Instance of class with specified Styler appended.
See Also
--------
Styler.clear : Reset the ``Styler``, removing any previously applied styles.
Styler.export : Export the styles applied to the current Styler.
Notes
-----
The purpose of this method is to extend existing styled dataframes with other
metrics that may be useful but may not conform to the original's structure.
For example adding a sub total row, or displaying metrics such as means,
variance or counts.
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::
Only the output methods ``to_html``, ``to_string`` and ``to_latex``
currently work with concatenated Stylers.
Other output methods, including ``to_excel``, **do not** work with
concatenated Stylers.
The following should be noted:
- ``table_styles``, ``table_attributes``, ``caption`` and ``uuid`` are all
inherited from the original Styler and not ``other``.
- hidden columns and hidden index levels will be inherited from the
original Styler
- ``css`` will be inherited from the original Styler, and the value of
keys ``data``, ``row_heading`` and ``row`` will be prepended with
``foot0_``. If more concats are chained, their styles will be prepended
with ``foot1_``, ''foot_2'', etc., and if a concatenated style have
another concatenated style, the second style will be prepended with
``foot{parent}_foot{child}_``.
A common use case is to concatenate user defined functions with
``DataFrame.agg`` or with described statistics via ``DataFrame.describe``.
See examples.
Examples
--------
A common use case is adding totals rows, or otherwise, via methods calculated
in ``DataFrame.agg``.
>>> df = pd.DataFrame(
... [[4, 6], [1, 9], [3, 4], [5, 5], [9, 6]],
... columns=["Mike", "Jim"],
... index=["Mon", "Tue", "Wed", "Thurs", "Fri"],
... )
>>> styler = df.style.concat(df.agg(["sum"]).style) # doctest: +SKIP
.. figure:: ../../_static/style/footer_simple.png
Since the concatenated object is a Styler the existing functionality can be
used to conditionally format it as well as the original.
>>> descriptors = df.agg(["sum", "mean", lambda s: s.dtype])
>>> descriptors.index = ["Total", "Average", "dtype"]
>>> other = (
... descriptors.style.highlight_max(
... axis=1, subset=(["Total", "Average"], slice(None))
... )
... .format(subset=("Average", slice(None)), precision=2, decimal=",")
... .map(lambda v: "font-weight: bold;")
... )
>>> styler = df.style.highlight_max(color="salmon").set_table_styles(
... [{"selector": ".foot_row0", "props": "border-top: 1px solid black;"}]
... )
>>> styler.concat(other) # doctest: +SKIP
.. figure:: ../../_static/style/footer_extended.png
When ``other`` has fewer index levels than the original Styler it is possible
to extend the index in ``other``, with placeholder levels.
>>> df = pd.DataFrame(
... [[1], [2]], index=pd.MultiIndex.from_product([[0], [1, 2]])
... )
>>> descriptors = df.agg(["sum"])
>>> descriptors.index = pd.MultiIndex.from_product([[""], descriptors.index])
>>> df.style.concat(descriptors.style) # doctest: +SKIP
"""
if not isinstance(other, Styler):
raise TypeError("`other` must be of type `Styler`")
if not self.data.columns.equals(other.data.columns):
raise ValueError("`other.data` must have same columns as `Styler.data`")
if not self.data.index.nlevels == other.data.index.nlevels:
raise ValueError(
"number of index levels must be same in `other` "
"as in `Styler`. See documentation for suggestions."
)
self.concatenated.append(other)
return self
def _repr_html_(self) -> str | None:
"""
Hooks into Jupyter notebook rich display system, which calls _repr_html_ by
default if an object is returned at the end of a cell.
"""
if get_option("styler.render.repr") == "html":
return self.to_html()
return None
def _repr_latex_(self) -> str | None:
if get_option("styler.render.repr") == "latex":
return self.to_latex()
return None
def set_tooltips(
self,
ttips: DataFrame,
props: CSSProperties | None = None,
css_class: str | None = None,
as_title_attribute: bool = False,
) -> Styler:
"""
Set the DataFrame of strings on ``Styler`` generating ``:hover`` tooltips.
These string based tooltips are only applicable to ``| `` HTML elements,
and cannot be used for column or index headers.
Parameters
----------
ttips : DataFrame
DataFrame containing strings that will be translated to tooltips, mapped
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'.
as_title_attribute : bool, default False
Add the tooltip text as title attribute to resultant | element. If True
then props and css_class arguments are ignored.
Returns
-------
Styler
Instance of class with DataFrame set for strings on ``Styler``
generating ``:hover`` tooltips.
See Also
--------
Styler.set_table_attributes : Set the table attributes added to the
```` HTML element.
Styler.set_table_styles : Set the table styles included within the
``
| |
A |
B |
...
"""
obj = self._copy(deepcopy=True) # manipulate table_styles on obj, not self
if table_uuid:
obj.set_uuid(table_uuid)
if table_attributes:
obj.set_table_attributes(table_attributes)
if sparse_index is None:
sparse_index = get_option("styler.sparse.index")
if sparse_columns is None:
sparse_columns = get_option("styler.sparse.columns")
if bold_headers:
obj.set_table_styles(
[{"selector": "th", "props": "font-weight: bold;"}], overwrite=False
)
if caption is not None:
obj.set_caption(caption)
# Build HTML string..
html = obj._render_html(
sparse_index=sparse_index,
sparse_columns=sparse_columns,
max_rows=max_rows,
max_cols=max_columns,
exclude_styles=exclude_styles,
encoding=encoding or get_option("styler.render.encoding"),
doctype_html=doctype_html,
**kwargs,
)
return save_to_buffer(
html, buf=buf, encoding=(encoding if buf is not None else None)
)
@overload
def to_string(
self,
buf: FilePath | WriteBuffer[str],
*,
encoding: str | None = ...,
sparse_index: bool | None = ...,
sparse_columns: bool | None = ...,
max_rows: int | None = ...,
max_columns: int | None = ...,
delimiter: str = ...,
) -> None: ...
@overload
def to_string(
self,
buf: None = ...,
*,
encoding: str | None = ...,
sparse_index: bool | None = ...,
sparse_columns: bool | None = ...,
max_rows: int | None = ...,
max_columns: int | None = ...,
delimiter: str = ...,
) -> str: ...
def to_string(
self,
buf: FilePath | WriteBuffer[str] | None = None,
*,
encoding: str | None = None,
sparse_index: bool | None = None,
sparse_columns: bool | None = None,
max_rows: int | None = None,
max_columns: int | None = None,
delimiter: str = " ",
) -> str | None:
"""
Write Styler to a file, buffer or string in text format.
Parameters
----------
buf : str, path object, file-like object, optional
String, path object (implementing ``os.PathLike[str]``), or file-like
object implementing a string ``write()`` function. If ``None``, the result
is returned as a string.
encoding : str, optional
Character encoding setting for file output (and meta tags if available).
Defaults to ``pandas.options.styler.render.encoding`` value of "utf-8".
sparse_index : bool, optional
Whether to sparsify the display of a hierarchical index. Setting to False
will display each explicit level element in a hierarchical key for each row.
Defaults to ``pandas.options.styler.sparse.index`` value.
sparse_columns : bool, optional
Whether to sparsify the display of a hierarchical index. Setting to False
will display each explicit level element in a hierarchical key for each
column. Defaults to ``pandas.options.styler.sparse.columns`` value.
max_rows : int, optional
The maximum number of rows that will be rendered. Defaults to
``pandas.options.styler.render.max_rows``, which is None.
max_columns : int, optional
The maximum number of columns that will be rendered. Defaults to
``pandas.options.styler.render.max_columns``, which is None.
Rows and columns may be reduced if the number of total elements is
large. This value is set to ``pandas.options.styler.render.max_elements``,
which is 262144 (18 bit browser rendering).
delimiter : str, default single space
The separator between data elements.
Returns
-------
str or None
If `buf` is None, returns the result as a string. Otherwise returns `None`.
See Also
--------
DataFrame.to_string : Render a DataFrame to a console-friendly tabular output.
Examples
--------
>>> df = pd.DataFrame({"A": [1, 2], "B": [3, 4]})
>>> df.style.to_string()
' A B\\n0 1 3\\n1 2 4\\n'
"""
obj = self._copy(deepcopy=True)
if sparse_index is None:
sparse_index = get_option("styler.sparse.index")
if sparse_columns is None:
sparse_columns = get_option("styler.sparse.columns")
text = obj._render_string(
sparse_columns=sparse_columns,
sparse_index=sparse_index,
max_rows=max_rows,
max_cols=max_columns,
delimiter=delimiter,
)
return save_to_buffer(
text, buf=buf, encoding=(encoding if buf is not None else None)
)
def set_td_classes(self, classes: DataFrame) -> Styler:
"""
Set the ``class`` attribute of ```` HTML elements.
Parameters
----------
classes : DataFrame
DataFrame containing strings that will be translated to CSS classes,
mapped by identical column and index key values that must exist on the
underlying Styler data. None, NaN values, and empty strings will
be ignored and not affect the rendered HTML.
Returns
-------
Styler
Instance of class with ``class`` attribute set for `` | ``
HTML elements.
See Also
--------
Styler.set_table_styles: Set the table styles included within the ``'
''
' '
' | 0 | '
' '
' '
' | 1 | '
' '
' '
"""
if not classes.index.is_unique or not classes.columns.is_unique:
raise KeyError(
"Classes render only if `classes` has unique index and columns."
)
classes = classes.reindex_like(self.data)
for r, row_tup in enumerate(classes.itertuples()):
for c, value in enumerate(row_tup[1:]):
if not (pd.isna(value) or value == ""):
self.cell_context[(r, c)] = str(value)
return self
def _update_ctx(self, attrs: DataFrame) -> None:
"""
Update the state of the ``Styler`` for data cells.
Collects a mapping of {index_label: [('', ''), ..]}.
Parameters
----------
attrs : DataFrame
should contain strings of ': ;: '
Whitespace shouldn't matter and the final trailing ';' shouldn't
matter.
"""
if not self.index.is_unique or not self.columns.is_unique:
raise KeyError(
"`Styler.apply` and `.map` are not compatible "
"with non-unique index or columns."
)
for cn in attrs.columns:
j = self.columns.get_loc(cn)
ser = attrs[cn]
for rn, c in ser.items():
if not c or pd.isna(c):
continue
css_list = maybe_convert_css_to_tuples(c)
i = self.index.get_loc(rn)
self.ctx[(i, j)].extend(css_list)
def _update_ctx_header(self, attrs: DataFrame, axis: AxisInt) -> None:
"""
Update the state of the ``Styler`` for header cells.
Collects a mapping of {index_label: [('', ''), ..]}.
Parameters
----------
attrs : Series
Should contain strings of ': ;: ', and an
integer index.
Whitespace shouldn't matter and the final trailing ';' shouldn't
matter.
axis : int
Identifies whether the ctx object being updated is the index or columns
"""
for j in attrs.columns:
ser = attrs[j]
for i, c in ser.items():
if not c or pd.isna(c):
continue
css_list = maybe_convert_css_to_tuples(c)
if axis == 0:
self.ctx_index[(i, j)].extend(css_list)
else:
self.ctx_columns[(j, i)].extend(css_list)
def _copy(self, deepcopy: bool = False) -> Styler:
"""
Copies a Styler, allowing for deepcopy or shallow copy
Copying a Styler aims to recreate a new Styler object which contains the same
data and styles as the original.
Data dependent attributes [copied and NOT exported]:
- formatting (._display_funcs)
- hidden index values or column values (.hidden_rows, .hidden_columns)
- tooltips
- cell_context (cell css classes)
- ctx (cell css styles)
- caption
- concatenated stylers
Non-data dependent attributes [copied and exported]:
- css
- hidden index state and hidden columns state (.hide_index_, .hide_columns_)
- table_attributes
- table_styles
- applied styles (_todo)
"""
# GH 40675, 52728
styler = type(self)(
self.data, # populates attributes 'data', 'columns', 'index' as shallow
)
shallow = [ # simple string or boolean immutables
"hide_index_",
"hide_columns_",
"hide_column_names",
"hide_index_names",
"table_attributes",
"cell_ids",
"caption",
"uuid",
"uuid_len",
"template_latex", # also copy templates if these have been customised
"template_html_style",
"template_html_table",
"template_html",
]
deep = [ # nested lists or dicts
"css",
"concatenated",
"_display_funcs",
"_display_funcs_index",
"_display_funcs_columns",
"_display_funcs_index_names",
"_display_funcs_column_names",
"hidden_rows",
"hidden_columns",
"ctx",
"ctx_index",
"ctx_columns",
"cell_context",
"_todo",
"table_styles",
"tooltips",
]
for attr in shallow:
setattr(styler, attr, getattr(self, attr))
for attr in deep:
val = getattr(self, attr)
setattr(styler, attr, copy.deepcopy(val) if deepcopy else val)
return styler
def __copy__(self) -> Styler:
return self._copy(deepcopy=False)
def __deepcopy__(self, memo) -> Styler:
return self._copy(deepcopy=True)
def clear(self) -> None:
"""
Reset the ``Styler``, removing any previously applied styles.
Returns None.
See Also
--------
Styler.apply : Apply a CSS-styling function column-wise, row-wise,
or table-wise.
Styler.export : Export the styles applied to the current Styler.
Styler.map : Apply a CSS-styling function elementwise.
Styler.use : Set the styles on the current Styler.
Examples
--------
>>> df = pd.DataFrame({"A": [1, 2], "B": [3, np.nan]})
After any added style:
>>> df.style.highlight_null(color="yellow") # doctest: +SKIP
Remove it with:
>>> df.style.clear() # doctest: +SKIP
Please see:
`Table Visualization <../../user_guide/style.ipynb>`_ for more examples.
"""
# create default GH 40675
clean_copy = Styler(self.data, uuid=self.uuid)
clean_attrs = [a for a in clean_copy.__dict__ if not callable(a)]
self_attrs = [a for a in self.__dict__ if not callable(a)] # maybe more attrs
for attr in clean_attrs:
setattr(self, attr, getattr(clean_copy, attr))
for attr in set(self_attrs).difference(clean_attrs):
delattr(self, attr)
def _apply(
self,
func: Callable,
axis: Axis | None = 0,
subset: Subset | None = None,
**kwargs,
) -> Styler:
subset = slice(None) if subset is None else subset
subset = non_reducing_slice(subset)
data = self.data.loc[subset]
if data.empty:
result = DataFrame()
elif axis is None:
result = func(data, **kwargs)
if not isinstance(result, DataFrame):
if not isinstance(result, np.ndarray):
raise TypeError(
f"Function {func!r} must return a DataFrame or ndarray "
f"when passed to `Styler.apply` with axis=None"
)
if data.shape != result.shape:
raise ValueError(
f"Function {func!r} returned ndarray with wrong shape.\n"
f"Result has shape: {result.shape}\n"
f"Expected shape: {data.shape}"
)
result = DataFrame(result, index=data.index, columns=data.columns)
else:
axis = self.data._get_axis_number(axis)
if axis == 0:
result = data.apply(func, axis=0, **kwargs)
else:
result = data.T.apply(func, axis=0, **kwargs).T # see GH 42005
if isinstance(result, Series):
raise ValueError(
f"Function {func!r} resulted in the apply method collapsing to a "
f"Series.\nUsually, this is the result of the function returning a "
f"single value, instead of list-like."
)
msg = (
f"Function {func!r} created invalid {{0}} labels.\nUsually, this is "
f"the result of the function returning a "
f"{'Series' if axis is not None else 'DataFrame'} which contains invalid "
f"labels, or returning an incorrectly shaped, list-like object which "
f"cannot be mapped to labels, possibly due to applying the function along "
f"the wrong axis.\n"
f"Result {{0}} has shape: {{1}}\n"
f"Expected {{0}} shape: {{2}}"
)
if not all(result.index.isin(data.index)):
raise ValueError(msg.format("index", result.index.shape, data.index.shape))
if not all(result.columns.isin(data.columns)):
raise ValueError(
msg.format("columns", result.columns.shape, data.columns.shape)
)
self._update_ctx(result)
return self
def apply(
self,
func: Callable,
axis: Axis | None = 0,
subset: Subset | None = None,
**kwargs,
) -> Styler:
"""
Apply a CSS-styling function column-wise, row-wise, or table-wise.
Updates the HTML representation with the result.
Parameters
----------
func : function
``func`` should take a Series if ``axis`` in [0,1] and return a list-like
object of same length, or a Series, not necessarily of same length, with
valid index labels considering ``subset``.
``func`` should take a DataFrame if ``axis`` is ``None`` and return either
an ndarray with the same shape or a DataFrame, not necessarily of the same
shape, with valid index and columns labels considering ``subset``.
axis : {0 or 'index', 1 or 'columns', None}, default 0
Apply to each column (``axis=0`` or ``'index'``), to each row
(``axis=1`` or ``'columns'``), or to the entire DataFrame at once
with ``axis=None``.
subset : label, array-like, IndexSlice, optional
A valid 2d input to `DataFrame.loc[]`, or, in the case of a 1d input
or single key, to `DataFrame.loc[:, ]` where the columns are
prioritised, to limit ``data`` to *before* applying the function.
**kwargs : dict
Pass along to ``func``.
Returns
-------
Styler
Instance of class with CSS applied to its HTML representation.
See Also
--------
Styler.map_index: Apply a CSS-styling function to headers elementwise.
Styler.apply_index: Apply a CSS-styling function to headers level-wise.
Styler.map: Apply a CSS-styling function elementwise.
Notes
-----
The elements of the output of ``func`` should be CSS styles as strings, in the
format 'attribute: value; attribute2: value2; ...' or,
if nothing is to be applied to that element, an empty string or ``None``.
This is similar to ``DataFrame.apply``, except that ``axis=None``
applies the function to the entire DataFrame at once,
rather than column-wise or row-wise.
Examples
--------
>>> def highlight_max(x, color):
... return np.where(x == np.nanmax(x.to_numpy()), f"color: {color};", None)
>>> df = pd.DataFrame(np.random.randn(5, 2), columns=["A", "B"])
>>> df.style.apply(highlight_max, color="red") # doctest: +SKIP
>>> df.style.apply(highlight_max, color="blue", axis=1) # doctest: +SKIP
>>> df.style.apply(highlight_max, color="green", axis=None) # doctest: +SKIP
Using ``subset`` to restrict application to a single column or multiple columns
>>> df.style.apply(highlight_max, color="red", subset="A")
... # doctest: +SKIP
>>> df.style.apply(highlight_max, color="red", subset=["A", "B"])
... # doctest: +SKIP
Using a 2d input to ``subset`` to select rows in addition to columns
>>> df.style.apply(highlight_max, color="red", subset=([0, 1, 2], slice(None)))
... # doctest: +SKIP
>>> df.style.apply(highlight_max, color="red", subset=(slice(0, 5, 2), "A"))
... # doctest: +SKIP
Using a function which returns a Series / DataFrame of unequal length but
containing valid index labels
>>> df = pd.DataFrame([[1, 2], [3, 4], [4, 6]], index=["A1", "A2", "Total"])
>>> total_style = pd.Series("font-weight: bold;", index=["Total"])
>>> df.style.apply(lambda s: total_style) # doctest: +SKIP
See `Table Visualization <../../user_guide/style.ipynb>`_ user guide for
more details.
"""
self._todo.append(
(lambda instance: instance._apply, (func, axis, subset), kwargs)
)
return self
def _apply_index(
self,
func: Callable,
axis: Axis = 0,
level: Level | list[Level] | None = None,
method: str = "apply",
**kwargs,
) -> Styler:
axis = self.data._get_axis_number(axis)
obj = self.index if axis == 0 else self.columns
levels_ = refactor_levels(level, obj)
data = DataFrame(obj.to_list()).loc[:, levels_]
if method == "apply":
result = data.apply(func, axis=0, **kwargs)
elif method == "map":
result = data.map(func, **kwargs)
self._update_ctx_header(result, axis)
return self
def apply_index(
self,
func: Callable,
axis: AxisInt | str = 0,
level: Level | list[Level] | None = None,
**kwargs,
) -> Styler:
"""
Apply a CSS-styling function to the index or column headers, level-wise.
Updates the HTML representation with the result.
.. versionadded:: 2.1.0
Styler.applymap_index was deprecated and renamed to Styler.map_index.
Parameters
----------
func : function
``func`` should take a Series and return a string array of the same length.
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
Instance of class with CSS applied to its HTML representation.
See Also
--------
Styler.map_index: Apply a CSS-styling function to headers elementwise.
Styler.apply: Apply a CSS-styling function column-wise, row-wise, or table-wise.
Styler.map: Apply a CSS-styling function elementwise.
Notes
-----
Each input to ``func`` will be the index as a Series, if an Index, or a level
of a MultiIndex. The output of ``func`` should be an identically sized array
of CSS styles as strings, in the format
'attribute: value; attribute2: value2; ...' or, if nothing is to be applied
to that element, an empty string or ``None``.
Examples
--------
Basic usage to conditionally highlight values in the index.
>>> df = pd.DataFrame([[1, 2], [3, 4]], index=["A", "B"])
>>> def color_b(label):
... return np.where(label == "B", "background-color: yellow;", "")
>>> df.style.apply_index(color_b) # doctest: +SKIP
.. figure:: ../../_static/style/appmaphead1.png
Selectively applying to specific levels of MultiIndex columns.
>>> midx = pd.MultiIndex.from_product([["ix", "jy"], [0, 1], ["x3", "z4"]])
>>> df = pd.DataFrame([np.arange(8)], columns=midx)
>>> def highlight_x(label):
... return ["background-color: yellow;" if "x" in v else "" for v in label]
>>> df.style.apply_index(
... highlight_x, axis="columns", level=[0, 2]
... ) # doctest: +SKIP
.. figure:: ../../_static/style/appmaphead2.png
"""
self._todo.append(
(
lambda instance: instance._apply_index,
(func, axis, level, "apply"),
kwargs,
)
)
return self
def map_index(
self,
func: Callable,
axis: AxisInt | str = 0,
level: Level | list[Level] | None = None,
**kwargs,
) -> Styler:
"""
Apply a CSS-styling function to the index or column headers, elementwise.
Updates the HTML representation with the result.
.. versionadded:: 2.1.0
Styler.applymap_index was deprecated and renamed to Styler.map_index.
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
Instance of class with CSS applied to its HTML representation.
See Also
--------
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.
Styler.map: Apply a CSS-styling function elementwise.
Notes
-----
Each input to ``func`` will be an index value, if an Index, or a level value of
a MultiIndex. The output of ``func`` should be CSS styles as a string, in the
format 'attribute: value; attribute2: value2; ...' or, if nothing is to be
applied to that element, an empty string or ``None``.
Examples
--------
Basic usage to conditionally highlight values in the index.
>>> df = pd.DataFrame([[1, 2], [3, 4]], index=["A", "B"])
>>> def color_b(label):
... return "background-color: yellow;" if label == "B" else None
>>> df.style.map_index(color_b) # doctest: +SKIP
.. figure:: ../../_static/style/appmaphead1.png
Selectively applying to specific levels of MultiIndex columns.
>>> midx = pd.MultiIndex.from_product([["ix", "jy"], [0, 1], ["x3", "z4"]])
>>> df = pd.DataFrame([np.arange(8)], columns=midx)
>>> def highlight_x(label):
... return "background-color: yellow;" if "x" in label else None
>>> df.style.map_index(
... highlight_x, axis="columns", level=[0, 2]
... ) # doctest: +SKIP
.. figure:: ../../_static/style/appmaphead2.png
"""
self._todo.append(
(
lambda instance: instance._apply_index,
(func, axis, level, "map"),
kwargs,
)
)
return self
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)
result = self.data.loc[subset].map(func)
self._update_ctx(result)
return self
def map(self, func: Callable, subset: Subset | None = None, **kwargs) -> Styler:
"""
Apply a CSS-styling function elementwise.
Updates the HTML representation with the result.
Parameters
----------
func : function
``func`` should take a scalar and return a string.
subset : label, array-like, IndexSlice, optional
A valid 2d input to `DataFrame.loc[]`, or, in the case of a 1d input
or single key, to `DataFrame.loc[:, ]` where the columns are
prioritised, to limit ``data`` to *before* applying the function.
**kwargs : dict
Pass along to ``func``.
Returns
-------
Styler
Instance of class with CSS-styling function applied elementwise.
See Also
--------
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.
Notes
-----
The elements of the output of ``func`` should be CSS styles as strings, in the
format 'attribute: value; attribute2: value2; ...' or,
if nothing is to be applied to that element, an empty string or ``None``.
Examples
--------
>>> 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.map(color_negative, color="red") # doctest: +SKIP
Using ``subset`` to restrict application to a single column or multiple columns
>>> df.style.map(color_negative, color="red", subset="A")
... # doctest: +SKIP
>>> 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.map(
... color_negative, color="red", subset=([0, 1, 2], slice(None))
... ) # doctest: +SKIP
>>> 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: instance._map, (func, subset), kwargs))
return self
def set_table_attributes(self, attributes: str) -> Styler:
"""
Set the table attributes added to the ```` HTML element.
These are items in addition to automatic (by default) ``id`` attribute.
Parameters
----------
attributes : str
Table attributes to be added to the ```` HTML element.
Returns
-------
Styler
Instance of class with specified table attributes set.
See Also
--------
Styler.set_table_styles: Set the table styles included within the `` | |