#!/usr/bin/env python # coding: utf-8 # *New in version 0.17.1* # #
*Provisional: This is a new feature and still under development. We'll be adding features and possibly making breaking changes in future releases. We'd love to hear your [feedback](https://github.com/pydata/pandas/issues).*
# # This document is written as a Jupyter Notebook, and can be viewed or downloaded [here](http://nbviewer.ipython.org/github/pydata/pandas/blob/master/doc/source/html-styling.ipynb). # # You can apply **conditional formatting**, the visual styling of a DataFrame # depending on the data within, by using the ``DataFrame.style`` property. # This is a property that returns a ``pandas.Styler`` object, which has # useful methods for formatting and displaying DataFrames. # # The styling is accomplished using CSS. # You write "style functions" that take scalars, `DataFrame`s or `Series`, and return *like-indexed* DataFrames or Series with CSS `"attribute: value"` pairs for the values. # These functions can be incrementally passed to the `Styler` which collects the styles before rendering. # # ### Contents # # - [Building Styles](#Building-Styles) # - [Finer Control: Slicing](#Finer-Control:-Slicing) # - [Builtin Styles](#Builtin-Styles) # - [Other options](#Other-options) # - [Sharing Styles](#Sharing-Styles) # - [Limitations](#Limitations) # - [Terms](#Terms) # - [Extensibility](#Extensibility) # # Building Styles # # Pass your style functions into one of the following methods: # # - `Styler.applymap`: elementwise # - `Styler.apply`: column-/row-/table-wise # # Both of those methods take a function (and some other keyword arguments) and applies your function to the DataFrame in a certain way. # `Styler.applymap` works through the DataFrame elementwise. # `Styler.apply` passes each column or row into your DataFrame one-at-a-time or the entire table at once, depending on the `axis` keyword argument. # For columnwise use `axis=0`, rowwise use `axis=1`, and for the entire table at once use `axis=None`. # # For `Styler.applymap` your function should take a scalar and return a single string with the CSS attribute-value pair. # # For `Styler.apply` your function should take a Series or DataFrame (depending on the axis parameter), and return a Series or DataFrame with an identical shape where each value is a string with a CSS attribute-value pair. # # Let's see some examples. # In[ ]: import pandas as pd import numpy as np np.random.seed(24) df = pd.DataFrame({'A': np.linspace(1, 10, 10)}) df = pd.concat([df, pd.DataFrame(np.random.randn(10, 4), columns=list('BCDE'))], axis=1) df.iloc[0, 2] = np.nan # Here's a boring example of rendering a DataFrame, without any (visible) styles: # In[ ]: df.style # *Note*: The `DataFrame.style` attribute is a propetry that returns a `Styler` object. `Styler` has a `_repr_html_` method defined on it so they are rendered automatically. If you want the actual HTML back for further processing or for writing to file call the `.render()` method which returns a string. # # The above output looks very similar to the standard DataFrame HTML representation. But we've done some work behind the scenes to attach CSS classes to each cell. We can view these by calling the `.render` method. # In[ ]: df.style.highlight_null().render().split('\n')[:10] # The `row0_col2` is the identifier for that particular cell. We've also prepended each row/column identifier with a UUID unique to each DataFrame so that the style from one doesn't collide with the styling from another within the same notebook or page (you can set the `uuid` if you'd like to tie together the styling of two DataFrames). # # When writing style functions, you take care of producing the CSS attribute / value pairs you want. Pandas matches those up with the CSS classes that identify each cell. # Let's write a simple style function that will color negative numbers red and positive numbers black. # In[ ]: def color_negative_red(val): """ Takes a scalar and returns a string with the css property `'color: red'` for negative strings, black otherwise. """ color = 'red' if val < 0 else 'black' return 'color: %s' % color # In this case, the cell's style depends only on it's own value. # That means we should use the `Styler.applymap` method which works elementwise. # In[ ]: s = df.style.applymap(color_negative_red) s # Notice the similarity with the standard `df.applymap`, which operates on DataFrames elementwise. We want you to be able to resuse your existing knowledge of how to interact with DataFrames. # # Notice also that our function returned a string containing the CSS attribute and value, separated by a colon just like in a `