Movatterモバイル変換


[0]ホーム

URL:


Skip to main content
Ctrl+K

Table Visualization#

This section demonstrates visualization of tabular data using theStyler class. For information on visualization with charting please seeChart Visualization. This document is written as a Jupyter Notebook, and can be viewed or downloadedhere.

Styler Object and Customising the Display#

Styling and output display customisation should be performedafter the data in a DataFrame has been processed. The Styler isnot dynamically updated if further changes to the DataFrame are made. TheDataFrame.style attribute is a property that returns aStyler object. It has a_repr_html_ method defined on it so it is rendered automatically in Jupyter Notebook.

The Styler, which can be used for large data but is primarily designed for small data, currently has the ability to output to these formats:

  • HTML

  • LaTeX

  • String (and CSV by extension)

  • Excel

  • (JSON is not currently available)

The first three of these have display customisation methods designed to format and customise the output. These include:

  • Formatting values, the index and columns headers, using.format() and.format_index(),

  • Renaming the index or column header labels, using.relabel_index()

  • Hiding certain columns, the index and/or column headers, or index names, using.hide()

  • Concatenating similar DataFrames, using.concat()

Formatting the Display#

Formatting Values#

TheStyler distinguishes thedisplay value from theactual value, in both data values and index or columns headers. To control the display value, the text is printed in each cell as a string, and we can use the.format() and.format_index() methods to manipulate this according to aformat specstring or a callable that takes a single value and returns a string. It is possible to define this for the whole table, or index, or for individual columns, or MultiIndex levels. We can also overwrite index names.

Additionally, the format function has aprecision argument to specifically help format floats, as well asdecimal andthousands separators to support other locales, anna_rep argument to display missing data, and anescape andhyperlinks arguments to help displaying safe-HTML or safe-LaTeX. The default formatter is configured to adopt pandas’ global options such asstyler.format.precision option, controllable usingwithpd.option_context('format.precision',2):

[2]:
importpandasaspdimportnumpyasnpimportmatplotlibasmpldf=pd.DataFrame({"strings":["Adam","Mike"],"ints":[1,3],"floats":[1.123,1000.23]})df.style \.format(precision=3,thousands=".",decimal=",") \.format_index(str.upper,axis=1) \.relabel_index(["row 1","row 2"],axis=0)
[2]:
 STRINGSINTSFLOATS
row 1Adam11,123
row 2Mike31.000,230

Using Styler to manipulate the display is a useful feature because maintaining the indexing and data values for other purposes gives greater control. You do not have to overwrite your DataFrame to display it how you like. Here is a more comprehensive example of using the formatting functions whilst still relying on the underlying data for indexing and calculations.

[3]:
weather_df=pd.DataFrame(np.random.rand(10,2)*5,index=pd.date_range(start="2021-01-01",periods=10),columns=["Tokyo","Beijing"])defrain_condition(v):ifv<1.75:return"Dry"elifv<2.75:return"Rain"return"Heavy Rain"defmake_pretty(styler):styler.set_caption("Weather Conditions")styler.format(rain_condition)styler.format_index(lambdav:v.strftime("%A"))styler.background_gradient(axis=None,vmin=1,vmax=5,cmap="YlGnBu")returnstylerweather_df
[3]:
TokyoBeijing
2021-01-011.3265741.455106
2021-01-024.4509560.565170
2021-01-031.7358454.738958
2021-01-044.5310864.057167
2021-01-051.4402941.345721
2021-01-063.1204152.185877
2021-01-074.3717094.907996
2021-01-082.1620971.980327
2021-01-094.6528742.665629
2021-01-101.2946713.058710
[4]:
weather_df.loc["2021-01-04":"2021-01-08"].style.pipe(make_pretty)
[4]:
Weather Conditions
 TokyoBeijing
MondayHeavy RainHeavy Rain
TuesdayDryDry
WednesdayHeavy RainRain
ThursdayHeavy RainHeavy Rain
FridayRainRain

Hiding Data#

The index and column headers can be completely hidden, as well subselecting rows or columns that one wishes to exclude. Both these options are performed using the same methods.

The index can be hidden from rendering by calling.hide() without any arguments, which might be useful if your index is integer based. Similarly column headers can be hidden by calling.hide(axis=”columns”) without any further arguments.

Specific rows or columns can be hidden from rendering by calling the same.hide() method and passing in a row/column label, a list-like or a slice of row/column labels to for thesubset argument.

Hiding does not change the integer arrangement of CSS classes, e.g. hiding the first two columns of a DataFrame means the column class indexing will still start atcol2, sincecol0 andcol1 are simply ignored.

[5]:
df=pd.DataFrame(np.random.randn(5,5))df.style \.hide(subset=[0,2,4],axis=0) \.hide(subset=[0,2,4],axis=1)
[5]:
 13
10.418223-0.308821
31.0283770.824383

To invert the function to ashow functionality it is best practice to compose a list of hidden items.

[6]:
show=[0,2,4]df.style \.hide([rowforrowindf.indexifrownotinshow],axis=0) \.hide([colforcolindf.columnsifcolnotinshow],axis=1)
[6]:
 024
0-0.069467-1.771927-1.073052
21.7865891.653543-0.527548
40.983244-0.774033-0.429712

Concatenating DataFrame Outputs#

Two or more Stylers can be concatenated together provided they share the same columns. This is very useful for showing summary statistics for a DataFrame, and is often used in combination with DataFrame.agg.

Since the objects concatenated are Stylers they can independently be styled as will be shown below and their concatenation preserves those styles.

[7]:
summary_styler=df.agg(["sum","mean"]).style \.format(precision=3) \.relabel_index(["Sum","Average"])df.style.format(precision=1).concat(summary_styler)
[7]:
 01234
0-0.1-0.8-1.8-0.5-1.1
1-0.90.42.1-0.3-1.0
21.80.31.7-2.2-0.5
31.11.0-2.90.80.4
41.00.8-0.80.1-0.4
Sum2.9091.663-1.707-2.053-2.630
Average0.5820.333-0.341-0.411-0.526

Styler Object and HTML#

TheStyler was originally constructed to support the wide array of HTML formatting options. Its HTML output creates an HTML<table> and leverages CSS styling language to manipulate many parameters including colors, fonts, borders, background, etc. Seehere for more information on styling HTML tables. This allows a lot of flexibility out of the box, and even enables web developers tointegrate DataFrames into their exiting user interface designs.

Below we demonstrate the default output, which looks very similar to the standard DataFrame HTML representation. But the HTML here has already attached some CSS classes to each cell, even if we haven’t yet created any styles. We can view these by calling the.to_html() method, which returns the raw HTML as string, which is useful for further processing or adding to a file - read on inMore about CSS andHTML. This section will also provide a walkthrough for how to convert this default output to represent a DataFrame output that is more communicative. For example how we can builds:

[8]:
df=pd.DataFrame([[38.0,2.0,18.0,22.0,21,np.nan],[19,439,6,452,226,232]],index=pd.Index(['Tumour (Positive)','Non-Tumour (Negative)'],name='Actual Label:'),columns=pd.MultiIndex.from_product([['Decision Tree','Regression','Random'],['Tumour','Non-Tumour']],names=['Model:','Predicted:']))df.style
[8]:
Model:Decision TreeRegressionRandom
Predicted:TumourNon-TumourTumourNon-TumourTumourNon-Tumour
Actual Label:      
Tumour (Positive)38.0000002.00000018.00000022.00000021nan
Non-Tumour (Negative)19.000000439.0000006.000000452.000000226232.000000
[10]:
s
[10]:
Confusion matrix for multiple cancer prediction models.
Model:Decision TreeRegression
Predicted:TumourNon-TumourTumourNon-Tumour
Actual Label:    
Tumour (Positive)3821822
Non-Tumour (Negative)194396452

The first step we have taken is the create the Styler object from the DataFrame and then select the range of interest by hiding unwanted columns with.hide().

[11]:
s=df.style.format('{:.0f}').hide([('Random','Tumour'),('Random','Non-Tumour')],axis="columns")s
[11]:
Model:Decision TreeRegression
Predicted:TumourNon-TumourTumourNon-Tumour
Actual Label:    
Tumour (Positive)3821822
Non-Tumour (Negative)194396452

Methods to Add Styles#

There are3 primary methods of adding custom CSS styles toStyler:

  • Using.set_table_styles() to control broader areas of the table with specified internal CSS. Although table styles allow the flexibility to add CSS selectors and properties controlling all individual parts of the table, they are unwieldy for individual cell specifications. Also, note that table styles cannot be exported to Excel.

  • Using.set_td_classes() to directly link either external CSS classes to your data cells or link the internal CSS classes created by.set_table_styles(). Seehere. These cannot be used on column header rows or indexes, and also won’t export to Excel.

  • Using the.apply() and.map() functions to add direct internal CSS to specific data cells. Seehere. As of v1.4.0 there are also methods that work directly on column header rows or indexes;.apply_index() and.map_index(). Note that only these methods add styles that will export to Excel. These methods work in a similar way toDataFrame.apply() andDataFrame.map().

Table Styles#

Table styles are flexible enough to control all individual parts of the table, including column headers and indexes. However, they can be unwieldy to type for individual data cells or for any kind of conditional formatting, so we recommend that table styles are used for broad styling, such as entire rows or columns at a time.

Table styles are also used to control features which can apply to the whole table at once such as creating a generic hover functionality. The:hover pseudo-selector, as well as other pseudo-selectors, can only be used this way.

To replicate the normal format of CSS selectors and properties (attribute value pairs), e.g.

tr:hover {  background-color: #ffff99;}

the necessary format to pass styles to.set_table_styles() is as a list of dicts, each with a CSS-selector tag and CSS-properties. Properties can either be a list of 2-tuples, or a regular CSS-string, for example:

[13]:
cell_hover={# for row hover use <tr> instead of <td>'selector':'td:hover','props':[('background-color','#ffffb3')]}index_names={'selector':'.index_name','props':'font-style: italic; color: darkgrey; font-weight:normal;'}headers={'selector':'th:not(.index_name)','props':'background-color: #000066; color: white;'}s.set_table_styles([cell_hover,index_names,headers])
[13]:
Model:Decision TreeRegression
Predicted:TumourNon-TumourTumourNon-Tumour
Actual Label:    
Tumour (Positive)3821822
Non-Tumour (Negative)194396452

Next we just add a couple more styling artifacts targeting specific parts of the table. Be careful here, since we arechaining methods we need to explicitly instruct the methodnot tooverwrite the existing styles.

[15]:
s.set_table_styles([{'selector':'th.col_heading','props':'text-align: center;'},{'selector':'th.col_heading.level0','props':'font-size: 1.5em;'},{'selector':'td','props':'text-align: center; font-weight: bold;'},],overwrite=False)
[15]:
Model:Decision TreeRegression
Predicted:TumourNon-TumourTumourNon-Tumour
Actual Label:    
Tumour (Positive)3821822
Non-Tumour (Negative)194396452

As a convenience method (since version 1.2.0) we can also pass adict to.set_table_styles() which contains row or column keys. Behind the scenes Styler just indexes the keys and adds relevant.col<m> or.row<n> classes as necessary to the given CSS selectors.

[17]:
s.set_table_styles({('Regression','Tumour'):[{'selector':'th','props':'border-left: 1px solid white'},{'selector':'td','props':'border-left: 1px solid #000066'}]},overwrite=False,axis=0)
[17]:
Model:Decision TreeRegression
Predicted:TumourNon-TumourTumourNon-Tumour
Actual Label:    
Tumour (Positive)3821822
Non-Tumour (Negative)194396452

Setting Classes and Linking to External CSS#

If you have designed a website then it is likely you will already have an external CSS file that controls the styling of table and cell objects within it. You may want to use these native files rather than duplicate all the CSS in python (and duplicate any maintenance work).

Table Attributes#

It is very easy to add aclass to the main<table> using.set_table_attributes(). This method can also attach inline styles - read more inCSS Hierarchies.

[19]:
out=s.set_table_attributes('class="my-table-cls"').to_html()print(out[out.find('<table'):][:109])
<table id="T_xyz01" class="my-table-cls">  <thead>    <tr>      <th class="index_name level0" >Model:</th>

Data Cell CSS Classes#

New in version 1.2.0

The.set_td_classes() method accepts a DataFrame with matching indices and columns to the underlyingStyler’s DataFrame. That DataFrame will contain strings as css-classes to add to individual data cells: the<td> elements of the<table>. Rather than use external CSS we will create our classes internally and add them to table style. We will save adding theborders until thesection on tooltips.

[20]:
s.set_table_styles([# create internal CSS classes{'selector':'.true','props':'background-color: #e6ffe6;'},{'selector':'.false','props':'background-color: #ffe6e6;'},],overwrite=False)cell_color=pd.DataFrame([['true ','false ','true ','false '],['false ','true ','false ','true ']],index=df.index,columns=df.columns[:4])s.set_td_classes(cell_color)
[20]:
Model:Decision TreeRegression
Predicted:TumourNon-TumourTumourNon-Tumour
Actual Label:    
Tumour (Positive)3821822
Non-Tumour (Negative)194396452

Styler Functions#

Acting on Data#

We use the following methods to pass your style functions. Both of those methods take a function (and some other keyword arguments) and apply it to the DataFrame in a certain way, rendering CSS styles.

  • .map() (elementwise): accepts a function that takes a single value and returns a string with the CSS attribute-value pair.

  • .apply() (column-/row-/table-wise): accepts a function that takes a Series or DataFrame and returns a Series, DataFrame, or numpy array with an identical shape where each element is a string with a CSS attribute-value pair. This method passes each column or row of your DataFrame one-at-a-time or the entire table at once, depending on theaxis keyword argument. For columnwise useaxis=0, rowwise useaxis=1, and for theentire table at once useaxis=None.

This method is powerful for applying multiple, complex logic to data cells. We create a new DataFrame to demonstrate this.

[22]:
np.random.seed(0)df2=pd.DataFrame(np.random.randn(10,4),columns=['A','B','C','D'])df2.style
[22]:
 ABCD
01.7640520.4001570.9787382.240893
11.867558-0.9772780.950088-0.151357
2-0.1032190.4105990.1440441.454274
30.7610380.1216750.4438630.333674
41.494079-0.2051580.313068-0.854096
5-2.5529900.6536190.864436-0.742165
62.269755-1.4543660.045759-0.187184
71.5327791.4693590.1549470.378163
8-0.887786-1.980796-0.3479120.156349
91.2302911.202380-0.387327-0.302303

For example we can build a function that colors text if it is negative, and chain this with a function that partially fades cells of negligible value. Since this looks at each element in turn we usemap.

[23]:
defstyle_negative(v,props=''):returnpropsifv<0elseNones2=df2.style.map(style_negative,props='color:red;')\.map(lambdav:'opacity: 20%;'if(v<0.3)and(v>-0.3)elseNone)s2
[23]:
 ABCD
01.7640520.4001570.9787382.240893
11.867558-0.9772780.950088-0.151357
2-0.1032190.4105990.1440441.454274
30.7610380.1216750.4438630.333674
41.494079-0.2051580.313068-0.854096
5-2.5529900.6536190.864436-0.742165
62.269755-1.4543660.045759-0.187184
71.5327791.4693590.1549470.378163
8-0.887786-1.980796-0.3479120.156349
91.2302911.202380-0.387327-0.302303

We can also build a function that highlights the maximum value across rows, cols, and the DataFrame all at once. In this case we useapply. Below we highlight the maximum in a column.

[25]:
defhighlight_max(s,props=''):returnnp.where(s==np.nanmax(s.values),props,'')s2.apply(highlight_max,props='color:white;background-color:darkblue',axis=0)
[25]:
 ABCD
01.7640520.4001570.9787382.240893
11.867558-0.9772780.950088-0.151357
2-0.1032190.4105990.1440441.454274
30.7610380.1216750.4438630.333674
41.494079-0.2051580.313068-0.854096
5-2.5529900.6536190.864436-0.742165
62.269755-1.4543660.045759-0.187184
71.5327791.4693590.1549470.378163
8-0.887786-1.980796-0.3479120.156349
91.2302911.202380-0.387327-0.302303

We can use the same function across the different axes, highlighting here the DataFrame maximum in purple, and row maximums in pink.

[27]:
s2.apply(highlight_max,props='color:white;background-color:pink;',axis=1)\.apply(highlight_max,props='color:white;background-color:purple',axis=None)
[27]:
 ABCD
01.7640520.4001570.9787382.240893
11.867558-0.9772780.950088-0.151357
2-0.1032190.4105990.1440441.454274
30.7610380.1216750.4438630.333674
41.494079-0.2051580.313068-0.854096
5-2.5529900.6536190.864436-0.742165
62.269755-1.4543660.045759-0.187184
71.5327791.4693590.1549470.378163
8-0.887786-1.980796-0.3479120.156349
91.2302911.202380-0.387327-0.302303

This last example shows how some styles have been overwritten by others. In general the most recent style applied is active but you can read more in thesection on CSS hierarchies. You can also apply these styles to more granular parts of the DataFrame - read more in section onsubset slicing.

It is possible to replicate some of this functionality using just classes but it can be more cumbersome. Seeitem 3) of Optimization

Debugging Tip: If you’re having trouble writing your style function, try just passing it intoDataFrame.apply. Internally,Styler.apply usesDataFrame.apply so the result should be the same, and withDataFrame.apply you will be able to inspect the CSS string output of your intended function in each cell.

Acting on the Index and Column Headers#

Similar application is achieved for headers by using:

  • .map_index() (elementwise): accepts a function that takes a single value and returns a string with the CSS attribute-value pair.

  • .apply_index() (level-wise): accepts a function that takes a Series and returns a Series, or numpy array with an identical shape where each element is a string with a CSS attribute-value pair. This method passes each level of your Index one-at-a-time. To style the index useaxis=0 and to style the column headers useaxis=1.

You can select alevel of aMultiIndex but currently no similarsubset application is available for these methods.

[29]:
s2.map_index(lambdav:"color:pink;"ifv>4else"color:darkblue;",axis=0)s2.apply_index(lambdas:np.where(s.isin(["A","B"]),"color:pink;","color:darkblue;"),axis=1)
[29]:
 ABCD
01.7640520.4001570.9787382.240893
11.867558-0.9772780.950088-0.151357
2-0.1032190.4105990.1440441.454274
30.7610380.1216750.4438630.333674
41.494079-0.2051580.313068-0.854096
5-2.5529900.6536190.864436-0.742165
62.269755-1.4543660.045759-0.187184
71.5327791.4693590.1549470.378163
8-0.887786-1.980796-0.3479120.156349
91.2302911.202380-0.387327-0.302303

Tooltips and Captions#

Table captions can be added with the.set_caption() method. You can use table styles to control the CSS relevant to the caption.

[30]:
s.set_caption("Confusion matrix for multiple cancer prediction models.")\.set_table_styles([{'selector':'caption','props':'caption-side: bottom; font-size:1.25em;'}],overwrite=False)
[30]:
Confusion matrix for multiple cancer prediction models.
Model:Decision TreeRegression
Predicted:TumourNon-TumourTumourNon-Tumour
Actual Label:    
Tumour (Positive)3821822
Non-Tumour (Negative)194396452

Adding tooltips (since version 1.3.0) can be done using the.set_tooltips() method in the same way you can add CSS classes to data cells by providing a string based DataFrame with intersecting indices and columns. You don’t have to specify acss_class name or any cssprops for the tooltips, since there are standard defaults, but the option is there if you want more visual control.

[32]:
tt=pd.DataFrame([['This model has a very strong true positive rate',"This model's total number of false negatives is too high"]],index=['Tumour (Positive)'],columns=df.columns[[0,3]])s.set_tooltips(tt,props='visibility: hidden; position: absolute; z-index: 1; border: 1px solid #000066;''background-color: white; color: #000066; font-size: 0.8em;''transform: translate(0px, -24px); padding: 0.6em; border-radius: 0.5em;')
[32]:
Confusion matrix for multiple cancer prediction models.
Model:Decision TreeRegression
Predicted:TumourNon-TumourTumourNon-Tumour
Actual Label:    
Tumour (Positive)3821822
Non-Tumour (Negative)194396452

The only thing left to do for our table is to add the highlighting borders to draw the audience attention to the tooltips. We will create internal CSS classes as before using table styles.Setting classes always overwrites so we need to make sure we add the previous classes.

[34]:
s.set_table_styles([# create internal CSS classes{'selector':'.border-red','props':'border: 2px dashed red;'},{'selector':'.border-green','props':'border: 2px dashed green;'},],overwrite=False)cell_border=pd.DataFrame([['border-green ',' ',' ','border-red '],[' ',' ',' ',' ']],index=df.index,columns=df.columns[:4])s.set_td_classes(cell_color+cell_border)
[34]:
Confusion matrix for multiple cancer prediction models.
Model:Decision TreeRegression
Predicted:TumourNon-TumourTumourNon-Tumour
Actual Label:    
Tumour (Positive)3821822
Non-Tumour (Negative)194396452

Finer Control with Slicing#

The examples we have shown so far for theStyler.apply andStyler.map functions have not demonstrated the use of thesubset argument. This is a useful argument which permits a lot of flexibility: it allows you to apply styles to specific rows or columns, without having to code that logic into yourstyle function.

The value passed tosubset behaves similar to slicing a DataFrame;

  • A scalar is treated as a column label

  • A list (or Series or NumPy array) is treated as multiple column labels

  • A tuple is treated as(row_indexer,column_indexer)

Consider usingpd.IndexSlice to construct the tuple for the last one. We will create a MultiIndexed DataFrame to demonstrate the functionality.

[36]:
df3=pd.DataFrame(np.random.randn(4,4),pd.MultiIndex.from_product([['A','B'],['r1','r2']]),columns=['c1','c2','c3','c4'])df3
[36]:
c1c2c3c4
Ar1-1.048553-1.420018-1.7062701.950775
r2-0.509652-0.438074-1.2527950.777490
Br1-1.613898-0.212740-0.8954670.386902
r2-0.510805-1.180632-0.0281820.428332

We will use subset to highlight the maximum in the third and fourth columns with red text. We will highlight the subset sliced region in yellow.

[37]:
slice_=['c3','c4']df3.style.apply(highlight_max,props='color:red;',axis=0,subset=slice_)\.set_properties(**{'background-color':'#ffffb3'},subset=slice_)
[37]:
  c1c2c3c4
Ar1-1.048553-1.420018-1.7062701.950775
r2-0.509652-0.438074-1.2527950.777490
Br1-1.613898-0.212740-0.8954670.386902
r2-0.510805-1.180632-0.0281820.428332

If combined with theIndexSlice as suggested then it can index across both dimensions with greater flexibility.

[38]:
idx=pd.IndexSliceslice_=idx[idx[:,'r1'],idx['c2':'c4']]df3.style.apply(highlight_max,props='color:red;',axis=0,subset=slice_)\.set_properties(**{'background-color':'#ffffb3'},subset=slice_)
[38]:
  c1c2c3c4
Ar1-1.048553-1.420018-1.7062701.950775
r2-0.509652-0.438074-1.2527950.777490
Br1-1.613898-0.212740-0.8954670.386902
r2-0.510805-1.180632-0.0281820.428332

This also provides the flexibility to sub select rows when used with theaxis=1.

[39]:
slice_=idx[idx[:,'r2'],:]df3.style.apply(highlight_max,props='color:red;',axis=1,subset=slice_)\.set_properties(**{'background-color':'#ffffb3'},subset=slice_)
[39]:
  c1c2c3c4
Ar1-1.048553-1.420018-1.7062701.950775
r2-0.509652-0.438074-1.2527950.777490
Br1-1.613898-0.212740-0.8954670.386902
r2-0.510805-1.180632-0.0281820.428332

There is also scope to provideconditional filtering.

Suppose we want to highlight the maximum across columns 2 and 4 only in the case that the sum of columns 1 and 3 is less than -2.0(essentially excluding rows(:,'r2')).

[40]:
slice_=idx[idx[(df3['c1']+df3['c3'])<-2.0],['c2','c4']]df3.style.apply(highlight_max,props='color:red;',axis=1,subset=slice_)\.set_properties(**{'background-color':'#ffffb3'},subset=slice_)
[40]:
  c1c2c3c4
Ar1-1.048553-1.420018-1.7062701.950775
r2-0.509652-0.438074-1.2527950.777490
Br1-1.613898-0.212740-0.8954670.386902
r2-0.510805-1.180632-0.0281820.428332

Only label-based slicing is supported right now, not positional, and not callables.

If your style function uses asubset oraxis keyword argument, consider wrapping your function in afunctools.partial, partialing out that keyword.

my_func2=functools.partial(my_func,subset=42)

Optimization#

Generally, for smaller tables and most cases, the rendered HTML does not need to be optimized, and we don’t really recommend it. There are two cases where it is worth considering:

  • If you are rendering and styling a very large HTML table, certain browsers have performance issues.

  • If you are usingStyler to dynamically create part of online user interfaces and want to improve network performance.

Here we recommend the following steps to implement:

1. Remove UUID and cell_ids#

Ignore theuuid and setcell_ids toFalse. This will prevent unnecessary HTML.

This is sub-optimal:

[41]:
df4=pd.DataFrame([[1,2],[3,4]])s4=df4.style

This is better:

[42]:
frompandas.io.formats.styleimportStylers4=Styler(df4,uuid_len=0,cell_ids=False)

2. Use table styles#

Use table styles where possible (e.g. for all cells or rows or columns at a time) since the CSS is nearly always more efficient than other formats.

This is sub-optimal:

[43]:
props='font-family: "Times New Roman", Times, serif; color: #e83e8c; font-size:1.3em;'df4.style.map(lambdax:props,subset=[1])
[43]:
 01
012
134

This is better:

[44]:
df4.style.set_table_styles([{'selector':'td.col1','props':props}])
[44]:
 01
012
134

3. Set classes instead of using Styler functions#

For large DataFrames where the same style is applied to many cells it can be more efficient to declare the styles as classes and then apply those classes to data cells, rather than directly applying styles to cells. It is, however, probably still easier to use the Styler function api when you are not concerned about optimization.

This is sub-optimal:

[45]:
df2.style.apply(highlight_max,props='color:white;background-color:darkblue;',axis=0)\.apply(highlight_max,props='color:white;background-color:pink;',axis=1)\.apply(highlight_max,props='color:white;background-color:purple',axis=None)
[45]:
 ABCD
01.7640520.4001570.9787382.240893
11.867558-0.9772780.950088-0.151357
2-0.1032190.4105990.1440441.454274
30.7610380.1216750.4438630.333674
41.494079-0.2051580.313068-0.854096
5-2.5529900.6536190.864436-0.742165
62.269755-1.4543660.045759-0.187184
71.5327791.4693590.1549470.378163
8-0.887786-1.980796-0.3479120.156349
91.2302911.202380-0.387327-0.302303

This is better:

[46]:
build=lambdax:pd.DataFrame(x,index=df2.index,columns=df2.columns)cls1=build(df2.apply(highlight_max,props='cls-1 ',axis=0))cls2=build(df2.apply(highlight_max,props='cls-2 ',axis=1,result_type='expand').values)cls3=build(highlight_max(df2,props='cls-3 '))df2.style.set_table_styles([{'selector':'.cls-1','props':'color:white;background-color:darkblue;'},{'selector':'.cls-2','props':'color:white;background-color:pink;'},{'selector':'.cls-3','props':'color:white;background-color:purple;'}]).set_td_classes(cls1+cls2+cls3)
[46]:
 ABCD
01.7640520.4001570.9787382.240893
11.867558-0.9772780.950088-0.151357
2-0.1032190.4105990.1440441.454274
30.7610380.1216750.4438630.333674
41.494079-0.2051580.313068-0.854096
5-2.5529900.6536190.864436-0.742165
62.269755-1.4543660.045759-0.187184
71.5327791.4693590.1549470.378163
8-0.887786-1.980796-0.3479120.156349
91.2302911.202380-0.387327-0.302303

4. Don’t use tooltips#

Tooltips requirecell_ids to work and they generate extra HTML elements forevery data cell.

5. If every byte counts use string replacement#

You can remove unnecessary HTML, or shorten the default class names by replacing the default css dict. You can read a little more about CSSbelow.

[47]:
my_css={"row_heading":"","col_heading":"","index_name":"","col":"c","row":"r","col_trim":"","row_trim":"","level":"l","data":"","blank":"",}html=Styler(df4,uuid_len=0,cell_ids=False)html.set_table_styles([{'selector':'td','props':props},{'selector':'.c1','props':'color:green;'},{'selector':'.l0','props':'color:blue;'}],css_class_names=my_css)print(html.to_html())
<style type="text/css">#T_ td {  font-family: "Times New Roman", Times, serif;  color: #e83e8c;  font-size: 1.3em;}#T_ .c1 {  color: green;}#T_ .l0 {  color: blue;}</style><table id="T_">  <thead>    <tr>      <th class=" l0" >&nbsp;</th>      <th class=" l0 c0" >0</th>      <th class=" l0 c1" >1</th>    </tr>  </thead>  <tbody>    <tr>      <th class=" l0 r0" >0</th>      <td class=" r0 c0" >1</td>      <td class=" r0 c1" >2</td>    </tr>    <tr>      <th class=" l0 r1" >1</th>      <td class=" r1 c0" >3</td>      <td class=" r1 c1" >4</td>    </tr>  </tbody></table>
[48]:
html
[48]:
 01
012
134

Builtin Styles#

Some styling functions are common enough that we’ve “built them in” to theStyler, so you don’t have to write them and apply them yourself. The current list of such functions is:

The individual documentation on each function often gives more examples of their arguments.

Highlight Null#

[49]:
df2.iloc[0,2]=np.nandf2.iloc[4,3]=np.nandf2.loc[:4].style.highlight_null(color='yellow')
[49]:
 ABCD
01.7640520.400157nan2.240893
11.867558-0.9772780.950088-0.151357
2-0.1032190.4105990.1440441.454274
30.7610380.1216750.4438630.333674
41.494079-0.2051580.313068nan

Highlight Min or Max#

[50]:
df2.loc[:4].style.highlight_max(axis=1,props='color:white; font-weight:bold; background-color:darkblue;')
[50]:
 ABCD
01.7640520.400157nan2.240893
11.867558-0.9772780.950088-0.151357
2-0.1032190.4105990.1440441.454274
30.7610380.1216750.4438630.333674
41.494079-0.2051580.313068nan

Highlight Between#

This method accepts ranges as float, or NumPy arrays or Series provided the indexes match.

[51]:
left=pd.Series([1.0,0.0,1.0],index=["A","B","D"])df2.loc[:4].style.highlight_between(left=left,right=1.5,axis=1,props='color:white; background-color:purple;')
[51]:
 ABCD
01.7640520.400157nan2.240893
11.867558-0.9772780.950088-0.151357
2-0.1032190.4105990.1440441.454274
30.7610380.1216750.4438630.333674
41.494079-0.2051580.313068nan

Highlight Quantile#

Useful for detecting the highest or lowest percentile values

[52]:
df2.loc[:4].style.highlight_quantile(q_left=0.85,axis=None,color='yellow')
[52]:
 ABCD
01.7640520.400157nan2.240893
11.867558-0.9772780.950088-0.151357
2-0.1032190.4105990.1440441.454274
30.7610380.1216750.4438630.333674
41.494079-0.2051580.313068nan

Background Gradient and Text Gradient#

You can create “heatmaps” with thebackground_gradient andtext_gradient methods. These require matplotlib, and we’ll useSeaborn to get a nice colormap.

[53]:
importseabornassnscm=sns.light_palette("green",as_cmap=True)df2.style.background_gradient(cmap=cm)
[53]:
 ABCD
01.7640520.400157nan2.240893
11.867558-0.9772780.950088-0.151357
2-0.1032190.4105990.1440441.454274
30.7610380.1216750.4438630.333674
41.494079-0.2051580.313068nan
5-2.5529900.6536190.864436-0.742165
62.269755-1.4543660.045759-0.187184
71.5327791.4693590.1549470.378163
8-0.887786-1.980796-0.3479120.156349
91.2302911.202380-0.387327-0.302303
[54]:
df2.style.text_gradient(cmap=cm)
[54]:
 ABCD
01.7640520.400157nan2.240893
11.867558-0.9772780.950088-0.151357
2-0.1032190.4105990.1440441.454274
30.7610380.1216750.4438630.333674
41.494079-0.2051580.313068nan
5-2.5529900.6536190.864436-0.742165
62.269755-1.4543660.045759-0.187184
71.5327791.4693590.1549470.378163
8-0.887786-1.980796-0.3479120.156349
91.2302911.202380-0.387327-0.302303

.background_gradient and.text_gradient have a number of keyword arguments to customise the gradients and colors. See the documentation.

Set properties#

UseStyler.set_properties when the style doesn’t actually depend on the values. This is just a simple wrapper for.map where the function returns the same properties for all cells.

[55]:
df2.loc[:4].style.set_properties(**{'background-color':'black','color':'lawngreen','border-color':'white'})
[55]:
 ABCD
01.7640520.400157nan2.240893
11.867558-0.9772780.950088-0.151357
2-0.1032190.4105990.1440441.454274
30.7610380.1216750.4438630.333674
41.494079-0.2051580.313068nan

Bar charts#

You can include “bar charts” in your DataFrame.

[56]:
df2.style.bar(subset=['A','B'],color='#d65f5f')
[56]:
 ABCD
01.7640520.400157nan2.240893
11.867558-0.9772780.950088-0.151357
2-0.1032190.4105990.1440441.454274
30.7610380.1216750.4438630.333674
41.494079-0.2051580.313068nan
5-2.5529900.6536190.864436-0.742165
62.269755-1.4543660.045759-0.187184
71.5327791.4693590.1549470.378163
8-0.887786-1.980796-0.3479120.156349
91.2302911.202380-0.387327-0.302303

Additional keyword arguments give more control on centering and positioning, and you can pass a list of[color_negative,color_positive] to highlight lower and higher values or a matplotlib colormap.

To showcase an example here’s how you can change the above with the newalign option, combined with settingvmin andvmax limits, thewidth of the figure, and underlying cssprops of cells, leaving space to display the text and the bars. We also usetext_gradient to color the text the same as the bars using a matplotlib colormap (although in this case the visualization is probably better without this additional effect).

[57]:
df2.style.format('{:.3f}',na_rep="")\.bar(align=0,vmin=-2.5,vmax=2.5,cmap="bwr",height=50,width=60,props="width: 120px; border-right: 1px solid black;")\.text_gradient(cmap="bwr",vmin=-2.5,vmax=2.5)
[57]:
 ABCD
01.7640.4002.241
11.868-0.9770.950-0.151
2-0.1030.4110.1441.454
30.7610.1220.4440.334
41.494-0.2050.313
5-2.5530.6540.864-0.742
62.270-1.4540.046-0.187
71.5331.4690.1550.378
8-0.888-1.981-0.3480.156
91.2301.202-0.387-0.302

The following example aims to give a highlight of the behavior of the new align options:

[59]:
HTML(head)
[59]:
AlignAll NegativeBoth Neg and PosAll PositiveLarge Positive
left
-100
-60
-30
-20
-10
-5
0
90
10
20
50
100
100
103
101
102
right
-100
-60
-30
-20
-10
-5
0
90
10
20
50
100
100
103
101
102
zero
-100
-60
-30
-20
-10
-5
0
90
10
20
50
100
100
103
101
102
mid
-100
-60
-30
-20
-10
-5
0
90
10
20
50
100
100
103
101
102
mean
-100
-60
-30
-20
-10
-5
0
90
10
20
50
100
100
103
101
102
99
-100
-60
-30
-20
-10
-5
0
90
10
20
50
100
100
103
101
102

Sharing styles#

Say you have a lovely style built up for a DataFrame, and now you want to apply the same style to a second DataFrame. Export the style withdf1.style.export, and import it on the second DataFrame withdf1.style.set

[60]:
style1=df2.style\.map(style_negative,props='color:red;')\.map(lambdav:'opacity: 20%;'if(v<0.3)and(v>-0.3)elseNone)\.set_table_styles([{"selector":"th","props":"color: blue;"}])\.hide(axis="index")style1
[60]:
ABCD
1.7640520.400157nan2.240893
1.867558-0.9772780.950088-0.151357
-0.1032190.4105990.1440441.454274
0.7610380.1216750.4438630.333674
1.494079-0.2051580.313068nan
-2.5529900.6536190.864436-0.742165
2.269755-1.4543660.045759-0.187184
1.5327791.4693590.1549470.378163
-0.887786-1.980796-0.3479120.156349
1.2302911.202380-0.387327-0.302303
[61]:
style2=df3.stylestyle2.use(style1.export())style2
[61]:
c1c2c3c4
-1.048553-1.420018-1.7062701.950775
-0.509652-0.438074-1.2527950.777490
-1.613898-0.212740-0.8954670.386902
-0.510805-1.180632-0.0281820.428332

Notice that you’re able to share the styles even though they’re data aware. The styles are re-evaluated on the new DataFrame they’ve beenused upon.

Limitations#

  • DataFrame only (useSeries.to_frame().style)

  • The index and columns do not need to be unique, but certain styling functions can only work with unique indexes.

  • No large repr, and construction performance isn’t great; although we have someHTML optimizations

  • You can only apply styles, you can’t insert new HTML entities, except via subclassing.

Other Fun and Useful Stuff#

Here are a few interesting examples.

Widgets#

Styler interacts pretty well with widgets. If you’re viewing this online instead of running the notebook yourself, you’re missing out on interactively adjusting the color palette.

[62]:
fromipywidgetsimportwidgets@widgets.interactdeff(h_neg=(0,359,1),h_pos=(0,359),s=(0.,99.9),l=(0.,99.9)):returndf2.style.background_gradient(cmap=sns.palettes.diverging_palette(h_neg=h_neg,h_pos=h_pos,s=s,l=l,as_cmap=True))

Magnify#

[63]:
defmagnify():return[dict(selector="th",props=[("font-size","4pt")]),dict(selector="td",props=[('padding',"0em 0em")]),dict(selector="th:hover",props=[("font-size","12pt")]),dict(selector="tr:hover td:hover",props=[('max-width','200px'),('font-size','12pt')])]
[64]:
np.random.seed(25)cmap=cmap=sns.diverging_palette(5,250,as_cmap=True)bigdf=pd.DataFrame(np.random.randn(20,25)).cumsum()bigdf.style.background_gradient(cmap,axis=1)\.set_properties(**{'max-width':'80px','font-size':'1pt'})\.set_caption("Hover to magnify")\.format(precision=2)\.set_table_styles(magnify())
[64]:
Hover to magnify
 0123456789101112131415161718192021222324
00.231.03-0.84-0.59-0.96-0.22-0.621.84-2.050.87-0.92-0.232.15-1.330.08-1.251.20-1.051.06-0.422.29-2.592.820.68-1.58
1-1.751.56-1.13-1.101.030.00-2.463.45-1.661.27-0.52-0.021.52-1.09-1.86-1.13-0.68-0.810.35-0.061.79-2.822.260.780.44
2-0.653.22-1.760.522.20-0.37-3.003.73-1.872.460.21-0.24-0.10-0.78-3.02-0.82-0.21-0.230.86-0.681.45-4.893.031.910.61
3-1.623.71-2.310.434.17-0.43-3.864.16-2.151.080.120.60-0.890.27-3.67-2.71-0.31-1.591.35-1.830.91-5.802.812.110.28
4-3.354.48-1.86-1.705.19-1.02-3.814.72-0.721.08-0.180.83-0.22-1.08-4.27-2.88-0.97-1.781.53-1.802.21-6.343.342.492.09
5-0.844.23-1.65-2.005.34-0.99-4.133.94-1.06-0.941.240.09-1.78-0.11-4.45-0.85-2.06-1.350.80-1.631.54-6.512.802.143.77
6-0.745.35-2.11-1.134.20-1.85-3.203.76-3.22-1.230.340.57-1.820.54-4.43-1.83-4.03-2.62-0.20-4.681.93-8.463.342.525.81
7-0.444.69-2.30-0.215.93-2.63-1.835.46-4.50-3.16-1.730.180.110.04-5.99-0.45-6.20-3.890.71-3.950.67-7.262.973.396.66
80.925.80-3.33-0.655.99-3.19-1.835.63-3.53-1.30-1.610.82-2.45-0.40-6.06-0.52-6.60-3.48-0.04-4.600.51-5.853.232.405.08
90.385.54-4.49-0.807.05-2.64-0.445.35-1.96-0.33-0.800.26-3.37-0.82-6.05-2.61-8.45-4.450.41-4.711.89-6.932.143.005.16
102.065.84-3.90-0.987.78-2.49-0.595.59-2.22-0.71-0.461.80-2.790.48-5.97-3.44-7.77-5.49-0.70-4.61-0.52-7.721.545.025.81
111.864.47-2.17-1.385.90-0.490.025.78-1.04-0.600.491.96-1.471.88-5.92-4.55-8.15-3.42-2.24-4.33-1.17-7.901.365.315.83
123.194.22-3.06-2.275.93-2.640.336.72-2.84-0.201.892.63-1.530.75-5.27-4.53-7.57-2.85-2.17-4.78-1.13-8.992.116.425.60
132.314.45-3.87-2.056.76-3.25-2.177.99-2.56-0.800.712.33-0.16-0.46-5.10-3.79-7.58-4.000.33-3.67-1.05-8.712.475.876.71
143.784.33-3.88-1.586.22-3.23-1.465.57-2.93-0.33-0.971.723.610.29-4.21-4.10-6.68-4.50-2.19-2.43-1.64-9.363.366.117.53
155.645.31-3.98-2.265.91-3.30-1.035.68-3.06-0.33-1.162.194.201.01-3.22-4.31-5.74-4.44-2.30-1.36-1.20-11.272.596.695.91
164.084.34-2.44-3.306.04-2.52-0.475.28-4.841.580.230.105.791.80-3.13-3.85-5.53-2.97-2.13-1.15-0.56-13.132.076.164.94
175.644.57-3.53-3.766.58-2.58-0.756.58-4.783.63-0.290.565.762.05-2.27-2.31-4.95-3.16-3.06-2.430.84-12.573.567.364.70
185.995.82-2.85-4.157.12-3.32-1.217.93-4.851.44-0.630.357.470.87-1.52-2.09-4.23-2.55-2.46-2.891.90-9.743.437.074.39
194.036.23-4.10-4.117.19-4.10-1.526.53-5.21-0.240.011.166.43-1.97-2.64-1.66-5.20-3.25-2.87-1.651.64-10.662.837.483.94

Sticky Headers#

If you display a large matrix or DataFrame in a notebook, but you want to always see the column and row headers you can use the.set_sticky method which manipulates the table styles CSS.

[65]:
bigdf=pd.DataFrame(np.random.randn(16,100))bigdf.style.set_sticky(axis="index")
[65]:
 0123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899
0-0.773866-0.240521-0.2171651.1736090.6863900.0083580.6962320.1731660.6204980.5040670.428066-0.0518240.7199150.0571650.562808-0.3695360.4833990.620765-0.354342-1.469471-1.9372660.038031-1.518162-0.4175990.3867170.7161930.4899610.7339570.9144150.6798940.255448-0.5083380.332030-0.111107-0.251983-1.4566200.4096301.062320-0.5771150.718796-0.399260-1.3113890.6491220.0915660.6288720.297894-0.142290-0.542291-0.9142901.1445140.3135841.1826351.214235-0.416446-1.653940-2.5507870.4424730.052127-0.464469-0.5238520.989726-1.325539-0.199687-1.2267270.2900181.1645740.817841-0.3095090.4965990.943536-0.091850-2.8026582.126219-0.5211610.288098-0.454663-1.676143-0.357661-0.7889600.185911-0.0171062.4540201.832706-0.911743-0.655873-0.000514-2.2269970.677285-0.140249-0.408407-0.8386650.4822281.243458-0.477394-0.220343-2.4639660.237325-0.3073801.1724780.819492
10.405906-0.9789191.2675260.145250-1.066786-2.114192-1.128346-1.0825230.3722160.004127-0.2119840.937326-0.935890-1.7041180.611789-1.0300150.636123-1.5061931.7366091.3929581.0094240.3532660.697339-0.2974240.428702-0.145346-0.333553-0.9746990.6653140.9719440.121950-1.4396681.0188081.442399-0.199585-1.1659160.6456561.436466-0.9212151.293906-2.7064431.460928-0.8231970.292952-1.4489920.026692-0.9758830.3928230.4421660.7457411.187982-0.2185700.3052880.054932-1.476953-0.1144340.0141030.825394-0.060654-0.4136880.9748361.3392101.0348380.0407750.7050010.0177961.867681-0.3901732.2852772.311464-0.085070-0.6481150.576300-0.790087-1.183798-1.334558-0.4541180.3193021.7064880.8304290.502476-0.0796310.4146350.3325110.042935-0.1609100.918553-0.292697-1.303834-0.1996040.871023-1.370681-0.205701-0.4929731.123083-0.081842-0.1185270.245838-0.315742-0.511806
20.011470-0.0361041.399603-0.418176-0.412229-1.234783-1.1215001.196478-0.5695220.422022-0.2204840.8043382.892667-0.511055-0.168722-1.477996-1.9699170.4713541.6985480.137105-0.7620520.199379-0.964346-0.2566921.2652750.848762-0.7841611.863776-0.3555690.8545520.768061-2.075718-2.5010691.1098680.957545-0.6832760.3077640.7330731.706250-1.1180910.374961-1.414503-0.524183-1.6626960.6879210.5217321.451396-0.833491-0.362796-1.174444-0.813893-0.8932200.7707431.156647-0.6474440.1259290.513600-0.5378741.992052-1.946584-0.1047590.484779-0.290936-0.4410750.542993-1.0500381.6304820.239771-1.1773100.464804-0.9669950.6460860.4868991.022196-2.267827-1.2296161.3138051.0732922.324940-0.542720-1.5042920.777643-0.6185530.0113421.3850621.363552-0.5498340.6888961.361288-0.3811370.797812-1.1281980.3692080.5401320.413853-0.200308-0.9691260.981293-0.009783-0.320020
3-0.5748161.4199770.434813-1.101217-1.5862751.9795730.3782980.7823262.1789870.6575640.683774-0.091000-0.059552-0.738908-0.907653-0.7019360.580039-0.6187570.4536841.665382-0.1523210.8800770.571073-0.6047360.5323590.515031-0.959844-0.8871840.4357810.862093-0.956321-0.6259090.1944720.4424900.526503-0.2152740.0907110.9325920.811999-2.4970260.6315450.321418-0.425549-1.0788320.7534440.199790-0.360526-0.013448-0.8194760.8148690.442118-0.972048-0.060603-2.3498251.265445-0.5732570.4291241.0497831.9547730.071883-0.0942090.2656160.9483180.3316451.343401-0.167934-1.105252-0.167077-0.096576-0.838161-0.2085640.3945340.7625331.235357-0.207282-0.202946-0.4680250.2569442.5875841.186697-1.0319031.4283160.658899-0.046582-0.0754221.329359-0.684267-1.5241822.0140613.7709330.647353-1.021377-0.3454930.5828110.7978121.3260201.422857-3.0770070.1840831.478935
4-0.6001421.929561-2.346771-0.669700-1.1652580.8147880.444449-0.5767580.3530910.4088930.091391-2.2943890.485506-0.081304-0.716272-1.6480101.005361-1.4896030.3630980.758602-1.373847-0.9720571.9885370.3198291.1690600.1465851.0303881.1659841.3695630.730984-1.383696-0.515189-0.808927-1.174651-1.631502-1.123414-0.478155-1.5830671.4190741.6687771.5675170.222103-0.336040-1.3520640.251032-0.4016950.268413-0.012299-0.9189532.921208-0.5815880.6728481.2511361.3822631.4298971.290990-1.272673-0.308611-0.422988-0.6756420.8744411.305736-0.262585-1.099395-0.667101-0.646737-0.556338-0.1965910.119306-0.266455-0.5242672.6509510.097318-0.9746970.1899641.141155-0.0644341.104971-1.508908-0.0318330.803919-0.6592210.9391450.214041-0.5318050.9560600.2493280.637903-0.5101581.850287-0.3484072.001376-0.389643-0.024786-0.4709730.8693390.1706670.5980621.2172621.274013
5-0.389981-0.752441-0.7348713.517318-1.173559-0.0049560.1454192.151368-3.086037-1.5691391.449784-0.868951-1.687716-0.9944011.1532661.803045-0.8190590.8479700.227102-0.5007620.8682101.8235401.161007-0.307606-0.7134160.363560-0.8221622.427681-0.129537-0.0787161.345644-1.2860940.237242-0.1360560.596664-1.4123811.2063410.2998600.7052380.142412-1.0593820.8334681.060015-0.527045-1.135732-1.140983-0.779540-0.640875-1.217196-1.6756630.241263-0.273322-1.697936-0.5949430.1011541.391735-0.4269531.008344-0.8185771.924570-0.578900-0.457395-1.0967050.418522-0.1556230.169706-2.5337060.0189041.4341600.7440950.647626-0.7703092.329141-0.141547-1.7615940.702091-1.531450-0.788427-0.184622-1.9423211.5301130.5034061.105845-0.935120-1.115483-2.2497621.3071350.788412-0.4410910.0735610.812101-0.9161461.573714-0.3095080.4999870.1875940.5589130.9032460.317901-0.809797
61.1282481.516826-0.186735-0.6681571.132259-0.246648-0.8551670.7322830.9318021.318684-1.198418-1.1493180.586321-1.171937-0.6077312.7537471.479287-1.136365-0.0204850.320444-1.9557550.660402-1.5453710.200519-0.0172631.6346860.5992460.4629890.0237210.2255460.170972-0.027496-0.061233-0.566411-0.6695670.6016180.503656-0.678253-2.907108-1.7171230.3976311.3001080.215821-0.593075-0.225944-0.9460571.0003080.3931601.342074-0.370687-0.166413-0.419814-0.2559311.7894780.2823780.742260-0.0504981.4153090.838166-1.400292-0.937976-1.4991480.8018590.2248240.2835720.643703-1.1984650.5272060.2152020.4370481.3128680.7412430.0779880.0061230.1903700.018007-1.026036-2.378430-1.0699490.8438221.289216-1.423369-0.4628870.197330-0.9350760.4412710.414643-0.377887-0.5305150.6215921.0095720.5697180.175291-0.656279-0.112273-0.392137-1.043558-0.467318-0.384329-2.009207
70.6585980.101830-0.6827810.229349-0.3056570.4048770.252244-0.837784-0.0396240.3294570.7516941.469070-0.1571991.032628-0.584639-0.9255440.342474-0.9693630.133480-0.385974-0.6002780.2819390.8685791.129803-0.0418980.9611930.131521-0.792889-1.2857370.073934-1.333315-1.0441251.2773381.4922570.4113791.771805-1.1111281.123233-1.0194491.738357-0.690764-0.120710-0.421359-0.727294-0.857759-0.069436-0.328334-0.5581801.063474-0.519133-0.4969021.089589-1.6158010.080174-0.229938-0.498420-0.6246150.059481-0.093158-1.784549-0.503789-0.1405280.002653-0.4849300.055914-0.680948-0.9942711.2770520.0376512.155421-0.4375890.6964040.417752-0.5447851.1906900.9782620.7521020.5044720.139853-0.505089-0.264975-1.6031940.7318470.010903-1.165346-0.125195-1.032685-0.4655201.5148080.3047620.7934140.314635-1.6382790.111737-0.7770370.2517831.126303-0.8087980.422064-0.349264
8-0.356362-0.0892270.6093730.542382-0.768681-0.0480742.015458-1.5523510.2515521.4596350.9497070.339465-0.0013721.7985891.5591630.2317830.423141-0.3105300.3537952.173336-0.196247-0.375636-0.8582210.2584100.6564300.9608191.1378931.5534050.038981-0.632038-0.132009-1.834997-0.242576-0.297879-0.441559-0.7696910.224077-0.1530090.519526-0.6801880.5358510.671496-0.1830640.3012341.288256-2.478240-0.3604030.424067-0.834659-0.128464-0.489013-0.014888-1.461230-1.435223-1.3198021.0836750.979140-0.3752911.110189-1.0113510.587886-0.822775-1.1838651.4551731.1343280.239403-0.837991-1.1309320.7831681.8455201.437072-1.1984431.3790982.1291130.260096-0.0119750.0433020.7229411.028152-0.2358061.145245-1.3595980.2321890.503712-0.614264-0.530606-2.435803-0.255238-0.0644230.7846430.2563460.1280231.414103-1.1186590.8773530.5005610.463651-2.034512-0.981683-0.691944
9-1.113376-1.1694020.680539-1.5342121.653817-1.295181-0.5668260.4770141.4133710.5171051.401153-0.8726850.8309570.181507-0.1456160.694592-0.7512080.3244440.681973-0.0549720.917776-1.024810-0.206446-0.6001130.8528051.455109-0.0797690.0760760.207699-1.850458-0.124124-0.610871-0.8833620.219049-0.685094-0.645330-0.242805-0.7756020.2330702.422642-1.423040-0.5824210.968304-0.701025-0.1678500.2772641.3012310.301205-3.081249-0.5628680.192944-0.6645920.5656860.190913-0.841858-1.856545-1.0227771.2959680.4519210.6599550.065818-0.3195860.253495-1.144646-0.4834040.5559020.8070690.7141960.6611960.0536670.346833-1.288977-0.386734-1.2621270.477495-0.494034-0.9114141.152963-0.342365-0.1601870.470054-0.853063-1.387949-0.257257-1.030690-0.1102100.328911-0.5559230.987713-0.5019572.069887-0.0675030.316029-1.5062322.2016210.492097-0.085193-0.9778221.039147-0.653932
10-0.405638-1.402027-1.1662421.3061840.856283-1.236170-0.646721-1.4740640.0829600.090310-0.1699770.4063450.915427-0.9745030.2716371.539184-0.098866-0.5251491.0639330.085827-0.1296220.947959-0.072496-0.2375920.0125491.0657610.996596-0.1724812.583139-0.028578-0.2548561.328794-1.5929512.434350-0.341500-0.307719-1.333273-1.1008450.2090971.7347770.6396320.424779-0.1293270.905029-0.4829091.731628-2.783425-0.333677-0.1108951.212636-0.2084120.4271171.3485630.0438591.772519-1.4161060.4011550.8071570.303427-1.2462880.178774-0.066126-1.8622881.2412950.377021-0.822320-0.7490141.4636521.602268-1.0438771.185290-0.565783-1.0768791.360241-0.1219910.9910431.0079520.450185-0.7443761.388876-0.316847-0.841655-1.056842-0.5002260.0969591.176896-2.9396521.7922130.3163400.3032181.024967-0.590871-0.453326-0.795981-0.393301-0.374372-1.2701991.6183721.197727-0.914863
11-0.6252100.2889110.288374-1.372667-0.591395-0.4789421.335664-0.459855-1.615975-1.1896760.374767-2.4887330.586656-1.4220080.4960301.911128-0.560660-0.499614-0.372171-1.8330690.237124-0.9444460.9121400.359790-1.3592350.166966-0.047107-0.279789-0.594454-0.739013-1.5276450.4016681.791252-2.7748480.5238732.2075850.488999-0.3392830.1317110.0184091.186551-0.4243181.554994-0.205917-0.9349750.654102-1.227761-0.461025-0.421201-0.058615-0.5845630.336913-0.477102-1.3814630.757745-0.2689680.0348701.2316860.2366001.234720-0.0402470.0295821.0349050.380204-0.012108-0.859511-0.990340-1.205172-1.0301780.4266760.497796-0.8768080.9579630.1730160.131612-1.003556-1.069908-1.7992071.429598-0.116015-1.4549800.2619170.4444120.2732900.8441150.218745-1.033350-1.1882950.0583730.800523-1.6270680.8616510.871018-0.003733-0.2433540.9472960.5094060.0445460.2668961.337165
120.699142-1.9280330.1053631.0423220.715206-0.7637830.098798-1.1578980.1341050.0420410.6748260.165649-1.622970-3.1312740.597649-1.8803310.663980-0.256033-1.5240580.4927990.2211630.429622-0.6595841.264506-0.032131-2.114907-0.2640430.457835-0.676837-0.6290030.489145-0.5516860.942622-0.512043-0.4558930.021244-0.178035-2.498073-0.1712920.323510-0.545163-0.668909-0.1500310.521620-0.4289800.6764630.369081-0.7248320.7935421.2374220.4012752.1415230.2490120.486755-0.1632740.592222-0.292600-0.5471680.619104-0.0136050.7767340.1314241.189480-0.666317-0.9390361.1055150.6214521.586605-0.7609701.6496460.2831991.275812-0.4520120.301361-0.976951-0.268106-0.079255-1.2583322.216658-1.175988-0.863497-1.653022-0.5615140.4507530.4172000.094676-2.2310541.316862-0.4774410.646654-0.2002521.074354-0.0581760.1209900.222522-0.1795070.421655-0.914341-0.2341780.741524
130.9327141.423761-1.2808350.347882-0.863171-0.8525801.0449332.0945360.8062060.416201-1.1095030.145302-0.9968710.325456-0.6050811.1753261.6450540.293432-2.7668221.0328490.079115-1.4141321.4633762.3354860.411951-0.0485430.159284-0.651554-1.0931281.568390-0.077807-2.390779-0.842346-0.229675-0.999072-1.367219-0.792042-1.8785751.4514521.266250-0.7343150.2661520.735523-0.4308600.2298640.850083-2.2412411.0638500.289409-0.3543600.113063-0.1730061.3869981.8862360.587119-0.9611330.3992951.4615600.3108230.280220-0.879103-1.3263480.003337-1.085908-0.4367232.1119260.1060680.6155972.152996-0.1961550.025747-0.0390610.656823-0.3471052.5139791.7580701.288473-0.739185-0.691592-0.098728-0.2763860.4899810.516278-0.8382580.596673-0.3310530.521174-0.1450230.836693-1.0921660.361733-1.1699810.0467310.655377-0.7568521.285805-0.0950190.3602531.3706210.083010
140.8888932.288725-1.0323320.212273-1.0918261.6924981.0253670.5508540.679430-1.335712-0.7983412.265351-1.0069382.0597610.420266-1.1896570.5066740.260847-0.5331450.7272671.4122761.482106-0.9962580.588641-0.412642-0.920733-0.8746910.8390020.501668-0.342493-0.533806-2.146352-0.5973390.1157260.850683-0.7522390.377263-0.5619820.262783-0.356676-0.3674620.753611-1.267414-1.330698-0.5364530.840938-0.763108-0.268100-0.6774241.6068310.151732-2.0857011.2192960.4008630.591165-1.4852131.5019791.196569-0.2141540.339554-0.0344461.1764520.546340-1.255630-1.309210-0.4454370.189437-0.7374630.843767-0.605632-0.0607770.4093101.285569-0.6226381.0181930.8806800.046805-1.818058-0.8098290.8752240.409569-0.116621-1.2389193.305724-0.024121-1.7565001.3289580.507593-0.866554-2.240848-0.661376-0.6718240.215720-0.2963260.4814020.829645-0.7210251.2639140.549047-1.234945
15-1.9788380.721823-0.559067-1.2352430.420716-0.5988450.359576-0.619366-1.757772-1.1562510.7052120.875071-1.0203760.394760-0.1479700.2302491.3552031.7944882.678058-0.153565-0.460959-0.098108-1.407930-2.4877021.8230140.099873-0.517603-0.509311-1.833175-0.9009060.459493-0.6554401.466122-1.531389-0.4221060.4214220.5786150.2597950.018941-0.1687261.611107-1.586550-1.3849410.8583771.0332421.7013431.748344-0.371182-0.8435752.089641-0.345430-1.7405560.141915-2.1971380.689569-0.1500250.2874560.654016-1.521919-0.918008-0.5875280.2306360.2626370.6156740.600044-0.494699-0.7430890.220026-0.2422070.528216-0.328174-1.536517-1.476640-1.162114-1.2602221.106252-1.467408-0.349341-1.8412170.031296-0.076475-0.3533830.8075450.779064-2.398417-0.2678281.5497340.8143970.284770-0.6593690.761040-0.7220670.8103321.5012951.440865-1.367459-0.700301-1.5406620.159837-0.625415

It is also possible to stick MultiIndexes and even only specific levels.

[66]:
bigdf.index=pd.MultiIndex.from_product([["A","B"],[0,1],[0,1,2,3]])bigdf.style.set_sticky(axis="index",pixel_size=18,levels=[1,2])
[66]:
   0123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899
A00-0.773866-0.240521-0.2171651.1736090.6863900.0083580.6962320.1731660.6204980.5040670.428066-0.0518240.7199150.0571650.562808-0.3695360.4833990.620765-0.354342-1.469471-1.9372660.038031-1.518162-0.4175990.3867170.7161930.4899610.7339570.9144150.6798940.255448-0.5083380.332030-0.111107-0.251983-1.4566200.4096301.062320-0.5771150.718796-0.399260-1.3113890.6491220.0915660.6288720.297894-0.142290-0.542291-0.9142901.1445140.3135841.1826351.214235-0.416446-1.653940-2.5507870.4424730.052127-0.464469-0.5238520.989726-1.325539-0.199687-1.2267270.2900181.1645740.817841-0.3095090.4965990.943536-0.091850-2.8026582.126219-0.5211610.288098-0.454663-1.676143-0.357661-0.7889600.185911-0.0171062.4540201.832706-0.911743-0.655873-0.000514-2.2269970.677285-0.140249-0.408407-0.8386650.4822281.243458-0.477394-0.220343-2.4639660.237325-0.3073801.1724780.819492
10.405906-0.9789191.2675260.145250-1.066786-2.114192-1.128346-1.0825230.3722160.004127-0.2119840.937326-0.935890-1.7041180.611789-1.0300150.636123-1.5061931.7366091.3929581.0094240.3532660.697339-0.2974240.428702-0.145346-0.333553-0.9746990.6653140.9719440.121950-1.4396681.0188081.442399-0.199585-1.1659160.6456561.436466-0.9212151.293906-2.7064431.460928-0.8231970.292952-1.4489920.026692-0.9758830.3928230.4421660.7457411.187982-0.2185700.3052880.054932-1.476953-0.1144340.0141030.825394-0.060654-0.4136880.9748361.3392101.0348380.0407750.7050010.0177961.867681-0.3901732.2852772.311464-0.085070-0.6481150.576300-0.790087-1.183798-1.334558-0.4541180.3193021.7064880.8304290.502476-0.0796310.4146350.3325110.042935-0.1609100.918553-0.292697-1.303834-0.1996040.871023-1.370681-0.205701-0.4929731.123083-0.081842-0.1185270.245838-0.315742-0.511806
20.011470-0.0361041.399603-0.418176-0.412229-1.234783-1.1215001.196478-0.5695220.422022-0.2204840.8043382.892667-0.511055-0.168722-1.477996-1.9699170.4713541.6985480.137105-0.7620520.199379-0.964346-0.2566921.2652750.848762-0.7841611.863776-0.3555690.8545520.768061-2.075718-2.5010691.1098680.957545-0.6832760.3077640.7330731.706250-1.1180910.374961-1.414503-0.524183-1.6626960.6879210.5217321.451396-0.833491-0.362796-1.174444-0.813893-0.8932200.7707431.156647-0.6474440.1259290.513600-0.5378741.992052-1.946584-0.1047590.484779-0.290936-0.4410750.542993-1.0500381.6304820.239771-1.1773100.464804-0.9669950.6460860.4868991.022196-2.267827-1.2296161.3138051.0732922.324940-0.542720-1.5042920.777643-0.6185530.0113421.3850621.363552-0.5498340.6888961.361288-0.3811370.797812-1.1281980.3692080.5401320.413853-0.200308-0.9691260.981293-0.009783-0.320020
3-0.5748161.4199770.434813-1.101217-1.5862751.9795730.3782980.7823262.1789870.6575640.683774-0.091000-0.059552-0.738908-0.907653-0.7019360.580039-0.6187570.4536841.665382-0.1523210.8800770.571073-0.6047360.5323590.515031-0.959844-0.8871840.4357810.862093-0.956321-0.6259090.1944720.4424900.526503-0.2152740.0907110.9325920.811999-2.4970260.6315450.321418-0.425549-1.0788320.7534440.199790-0.360526-0.013448-0.8194760.8148690.442118-0.972048-0.060603-2.3498251.265445-0.5732570.4291241.0497831.9547730.071883-0.0942090.2656160.9483180.3316451.343401-0.167934-1.105252-0.167077-0.096576-0.838161-0.2085640.3945340.7625331.235357-0.207282-0.202946-0.4680250.2569442.5875841.186697-1.0319031.4283160.658899-0.046582-0.0754221.329359-0.684267-1.5241822.0140613.7709330.647353-1.021377-0.3454930.5828110.7978121.3260201.422857-3.0770070.1840831.478935
10-0.6001421.929561-2.346771-0.669700-1.1652580.8147880.444449-0.5767580.3530910.4088930.091391-2.2943890.485506-0.081304-0.716272-1.6480101.005361-1.4896030.3630980.758602-1.373847-0.9720571.9885370.3198291.1690600.1465851.0303881.1659841.3695630.730984-1.383696-0.515189-0.808927-1.174651-1.631502-1.123414-0.478155-1.5830671.4190741.6687771.5675170.222103-0.336040-1.3520640.251032-0.4016950.268413-0.012299-0.9189532.921208-0.5815880.6728481.2511361.3822631.4298971.290990-1.272673-0.308611-0.422988-0.6756420.8744411.305736-0.262585-1.099395-0.667101-0.646737-0.556338-0.1965910.119306-0.266455-0.5242672.6509510.097318-0.9746970.1899641.141155-0.0644341.104971-1.508908-0.0318330.803919-0.6592210.9391450.214041-0.5318050.9560600.2493280.637903-0.5101581.850287-0.3484072.001376-0.389643-0.024786-0.4709730.8693390.1706670.5980621.2172621.274013
1-0.389981-0.752441-0.7348713.517318-1.173559-0.0049560.1454192.151368-3.086037-1.5691391.449784-0.868951-1.687716-0.9944011.1532661.803045-0.8190590.8479700.227102-0.5007620.8682101.8235401.161007-0.307606-0.7134160.363560-0.8221622.427681-0.129537-0.0787161.345644-1.2860940.237242-0.1360560.596664-1.4123811.2063410.2998600.7052380.142412-1.0593820.8334681.060015-0.527045-1.135732-1.140983-0.779540-0.640875-1.217196-1.6756630.241263-0.273322-1.697936-0.5949430.1011541.391735-0.4269531.008344-0.8185771.924570-0.578900-0.457395-1.0967050.418522-0.1556230.169706-2.5337060.0189041.4341600.7440950.647626-0.7703092.329141-0.141547-1.7615940.702091-1.531450-0.788427-0.184622-1.9423211.5301130.5034061.105845-0.935120-1.115483-2.2497621.3071350.788412-0.4410910.0735610.812101-0.9161461.573714-0.3095080.4999870.1875940.5589130.9032460.317901-0.809797
21.1282481.516826-0.186735-0.6681571.132259-0.246648-0.8551670.7322830.9318021.318684-1.198418-1.1493180.586321-1.171937-0.6077312.7537471.479287-1.136365-0.0204850.320444-1.9557550.660402-1.5453710.200519-0.0172631.6346860.5992460.4629890.0237210.2255460.170972-0.027496-0.061233-0.566411-0.6695670.6016180.503656-0.678253-2.907108-1.7171230.3976311.3001080.215821-0.593075-0.225944-0.9460571.0003080.3931601.342074-0.370687-0.166413-0.419814-0.2559311.7894780.2823780.742260-0.0504981.4153090.838166-1.400292-0.937976-1.4991480.8018590.2248240.2835720.643703-1.1984650.5272060.2152020.4370481.3128680.7412430.0779880.0061230.1903700.018007-1.026036-2.378430-1.0699490.8438221.289216-1.423369-0.4628870.197330-0.9350760.4412710.414643-0.377887-0.5305150.6215921.0095720.5697180.175291-0.656279-0.112273-0.392137-1.043558-0.467318-0.384329-2.009207
30.6585980.101830-0.6827810.229349-0.3056570.4048770.252244-0.837784-0.0396240.3294570.7516941.469070-0.1571991.032628-0.584639-0.9255440.342474-0.9693630.133480-0.385974-0.6002780.2819390.8685791.129803-0.0418980.9611930.131521-0.792889-1.2857370.073934-1.333315-1.0441251.2773381.4922570.4113791.771805-1.1111281.123233-1.0194491.738357-0.690764-0.120710-0.421359-0.727294-0.857759-0.069436-0.328334-0.5581801.063474-0.519133-0.4969021.089589-1.6158010.080174-0.229938-0.498420-0.6246150.059481-0.093158-1.784549-0.503789-0.1405280.002653-0.4849300.055914-0.680948-0.9942711.2770520.0376512.155421-0.4375890.6964040.417752-0.5447851.1906900.9782620.7521020.5044720.139853-0.505089-0.264975-1.6031940.7318470.010903-1.165346-0.125195-1.032685-0.4655201.5148080.3047620.7934140.314635-1.6382790.111737-0.7770370.2517831.126303-0.8087980.422064-0.349264
B00-0.356362-0.0892270.6093730.542382-0.768681-0.0480742.015458-1.5523510.2515521.4596350.9497070.339465-0.0013721.7985891.5591630.2317830.423141-0.3105300.3537952.173336-0.196247-0.375636-0.8582210.2584100.6564300.9608191.1378931.5534050.038981-0.632038-0.132009-1.834997-0.242576-0.297879-0.441559-0.7696910.224077-0.1530090.519526-0.6801880.5358510.671496-0.1830640.3012341.288256-2.478240-0.3604030.424067-0.834659-0.128464-0.489013-0.014888-1.461230-1.435223-1.3198021.0836750.979140-0.3752911.110189-1.0113510.587886-0.822775-1.1838651.4551731.1343280.239403-0.837991-1.1309320.7831681.8455201.437072-1.1984431.3790982.1291130.260096-0.0119750.0433020.7229411.028152-0.2358061.145245-1.3595980.2321890.503712-0.614264-0.530606-2.435803-0.255238-0.0644230.7846430.2563460.1280231.414103-1.1186590.8773530.5005610.463651-2.034512-0.981683-0.691944
1-1.113376-1.1694020.680539-1.5342121.653817-1.295181-0.5668260.4770141.4133710.5171051.401153-0.8726850.8309570.181507-0.1456160.694592-0.7512080.3244440.681973-0.0549720.917776-1.024810-0.206446-0.6001130.8528051.455109-0.0797690.0760760.207699-1.850458-0.124124-0.610871-0.8833620.219049-0.685094-0.645330-0.242805-0.7756020.2330702.422642-1.423040-0.5824210.968304-0.701025-0.1678500.2772641.3012310.301205-3.081249-0.5628680.192944-0.6645920.5656860.190913-0.841858-1.856545-1.0227771.2959680.4519210.6599550.065818-0.3195860.253495-1.144646-0.4834040.5559020.8070690.7141960.6611960.0536670.346833-1.288977-0.386734-1.2621270.477495-0.494034-0.9114141.152963-0.342365-0.1601870.470054-0.853063-1.387949-0.257257-1.030690-0.1102100.328911-0.5559230.987713-0.5019572.069887-0.0675030.316029-1.5062322.2016210.492097-0.085193-0.9778221.039147-0.653932
2-0.405638-1.402027-1.1662421.3061840.856283-1.236170-0.646721-1.4740640.0829600.090310-0.1699770.4063450.915427-0.9745030.2716371.539184-0.098866-0.5251491.0639330.085827-0.1296220.947959-0.072496-0.2375920.0125491.0657610.996596-0.1724812.583139-0.028578-0.2548561.328794-1.5929512.434350-0.341500-0.307719-1.333273-1.1008450.2090971.7347770.6396320.424779-0.1293270.905029-0.4829091.731628-2.783425-0.333677-0.1108951.212636-0.2084120.4271171.3485630.0438591.772519-1.4161060.4011550.8071570.303427-1.2462880.178774-0.066126-1.8622881.2412950.377021-0.822320-0.7490141.4636521.602268-1.0438771.185290-0.565783-1.0768791.360241-0.1219910.9910431.0079520.450185-0.7443761.388876-0.316847-0.841655-1.056842-0.5002260.0969591.176896-2.9396521.7922130.3163400.3032181.024967-0.590871-0.453326-0.795981-0.393301-0.374372-1.2701991.6183721.197727-0.914863
3-0.6252100.2889110.288374-1.372667-0.591395-0.4789421.335664-0.459855-1.615975-1.1896760.374767-2.4887330.586656-1.4220080.4960301.911128-0.560660-0.499614-0.372171-1.8330690.237124-0.9444460.9121400.359790-1.3592350.166966-0.047107-0.279789-0.594454-0.739013-1.5276450.4016681.791252-2.7748480.5238732.2075850.488999-0.3392830.1317110.0184091.186551-0.4243181.554994-0.205917-0.9349750.654102-1.227761-0.461025-0.421201-0.058615-0.5845630.336913-0.477102-1.3814630.757745-0.2689680.0348701.2316860.2366001.234720-0.0402470.0295821.0349050.380204-0.012108-0.859511-0.990340-1.205172-1.0301780.4266760.497796-0.8768080.9579630.1730160.131612-1.003556-1.069908-1.7992071.429598-0.116015-1.4549800.2619170.4444120.2732900.8441150.218745-1.033350-1.1882950.0583730.800523-1.6270680.8616510.871018-0.003733-0.2433540.9472960.5094060.0445460.2668961.337165
100.699142-1.9280330.1053631.0423220.715206-0.7637830.098798-1.1578980.1341050.0420410.6748260.165649-1.622970-3.1312740.597649-1.8803310.663980-0.256033-1.5240580.4927990.2211630.429622-0.6595841.264506-0.032131-2.114907-0.2640430.457835-0.676837-0.6290030.489145-0.5516860.942622-0.512043-0.4558930.021244-0.178035-2.498073-0.1712920.323510-0.545163-0.668909-0.1500310.521620-0.4289800.6764630.369081-0.7248320.7935421.2374220.4012752.1415230.2490120.486755-0.1632740.592222-0.292600-0.5471680.619104-0.0136050.7767340.1314241.189480-0.666317-0.9390361.1055150.6214521.586605-0.7609701.6496460.2831991.275812-0.4520120.301361-0.976951-0.268106-0.079255-1.2583322.216658-1.175988-0.863497-1.653022-0.5615140.4507530.4172000.094676-2.2310541.316862-0.4774410.646654-0.2002521.074354-0.0581760.1209900.222522-0.1795070.421655-0.914341-0.2341780.741524
10.9327141.423761-1.2808350.347882-0.863171-0.8525801.0449332.0945360.8062060.416201-1.1095030.145302-0.9968710.325456-0.6050811.1753261.6450540.293432-2.7668221.0328490.079115-1.4141321.4633762.3354860.411951-0.0485430.159284-0.651554-1.0931281.568390-0.077807-2.390779-0.842346-0.229675-0.999072-1.367219-0.792042-1.8785751.4514521.266250-0.7343150.2661520.735523-0.4308600.2298640.850083-2.2412411.0638500.289409-0.3543600.113063-0.1730061.3869981.8862360.587119-0.9611330.3992951.4615600.3108230.280220-0.879103-1.3263480.003337-1.085908-0.4367232.1119260.1060680.6155972.152996-0.1961550.025747-0.0390610.656823-0.3471052.5139791.7580701.288473-0.739185-0.691592-0.098728-0.2763860.4899810.516278-0.8382580.596673-0.3310530.521174-0.1450230.836693-1.0921660.361733-1.1699810.0467310.655377-0.7568521.285805-0.0950190.3602531.3706210.083010
20.8888932.288725-1.0323320.212273-1.0918261.6924981.0253670.5508540.679430-1.335712-0.7983412.265351-1.0069382.0597610.420266-1.1896570.5066740.260847-0.5331450.7272671.4122761.482106-0.9962580.588641-0.412642-0.920733-0.8746910.8390020.501668-0.342493-0.533806-2.146352-0.5973390.1157260.850683-0.7522390.377263-0.5619820.262783-0.356676-0.3674620.753611-1.267414-1.330698-0.5364530.840938-0.763108-0.268100-0.6774241.6068310.151732-2.0857011.2192960.4008630.591165-1.4852131.5019791.196569-0.2141540.339554-0.0344461.1764520.546340-1.255630-1.309210-0.4454370.189437-0.7374630.843767-0.605632-0.0607770.4093101.285569-0.6226381.0181930.8806800.046805-1.818058-0.8098290.8752240.409569-0.116621-1.2389193.305724-0.024121-1.7565001.3289580.507593-0.866554-2.240848-0.661376-0.6718240.215720-0.2963260.4814020.829645-0.7210251.2639140.549047-1.234945
3-1.9788380.721823-0.559067-1.2352430.420716-0.5988450.359576-0.619366-1.757772-1.1562510.7052120.875071-1.0203760.394760-0.1479700.2302491.3552031.7944882.678058-0.153565-0.460959-0.098108-1.407930-2.4877021.8230140.099873-0.517603-0.509311-1.833175-0.9009060.459493-0.6554401.466122-1.531389-0.4221060.4214220.5786150.2597950.018941-0.1687261.611107-1.586550-1.3849410.8583771.0332421.7013431.748344-0.371182-0.8435752.089641-0.345430-1.7405560.141915-2.1971380.689569-0.1500250.2874560.654016-1.521919-0.918008-0.5875280.2306360.2626370.6156740.600044-0.494699-0.7430890.220026-0.2422070.528216-0.328174-1.536517-1.476640-1.162114-1.2602221.106252-1.467408-0.349341-1.8412170.031296-0.076475-0.3533830.8075450.779064-2.398417-0.2678281.5497340.8143970.284770-0.6593690.761040-0.7220670.8103321.5012951.440865-1.367459-0.700301-1.5406620.159837-0.625415

HTML Escaping#

Suppose you have to display HTML within HTML, that can be a bit of pain when the renderer can’t distinguish. You can use theescape formatting option to handle this, and even use it within a formatter that contains HTML itself.

[67]:
df4=pd.DataFrame([['<div></div>','"&other"','<span></span>']])df4.style
[67]:
 012
0
"&other"
[68]:
df4.style.format(escape="html")
[68]:
 012
0<div></div>"&other"<span></span>
[69]:
df4.style.format('<a href="https://pandas.pydata.org" target="_blank">{}</a>',escape="html")

Export to Excel#

Some support (since version 0.20.0) is available for exporting styledDataFrames to Excel worksheets using theOpenPyXL orXlsxWriter engines. CSS2.2 properties handled include:

  • background-color

  • border-style properties

  • border-width properties

  • border-color properties

  • color

  • font-family

  • font-style

  • font-weight

  • text-align

  • text-decoration

  • vertical-align

  • white-space:nowrap

  • Shorthand and side-specific border properties are supported (e.g.border-style andborder-left-style) as well as theborder shorthands for all sides (border:1pxsolidgreen) or specified sides (border-left:1pxsolidgreen). Using aborder shorthand will override any border properties set before it (SeeCSS Working Group for more details)

  • Only CSS2 named colors and hex colors of the form#rgb or#rrggbb are currently supported.

  • The following pseudo CSS properties are also available to set Excel specific style properties:

    • number-format

    • border-style (for Excel-specific styles: “hair”, “mediumDashDot”, “dashDotDot”, “mediumDashDotDot”, “dashDot”, “slantDashDot”, or “mediumDashed”)

Table level styles, and data cell CSS-classes are not included in the export to Excel: individual cells must have their properties mapped by theStyler.apply and/orStyler.map methods.

[70]:
df2.style.\map(style_negative,props='color:red;').\highlight_max(axis=0).\to_excel('styled.xlsx',engine='openpyxl')

A screenshot of the output:

Excel spreadsheet with styled DataFrame

Export to LaTeX#

There is support (since version 1.3.0) to exportStyler to LaTeX. The documentation for the.to_latex method gives further detail and numerous examples.

More About CSS and HTML#

Cascading Style Sheet (CSS) language, which is designed to influence how a browser renders HTML elements, has its own peculiarities. It never reports errors: it just silently ignores them and doesn’t render your objects how you intend so can sometimes be frustrating. Here is a very brief primer on howStyler creates HTML and interacts with CSS, with advice on common pitfalls to avoid.

CSS Classes and Ids#

The precise structure of the CSSclass attached to each cell is as follows.

  • Cells with Index and Column names includeindex_name andlevel<k> wherek is its level in a MultiIndex

  • Index label cells include

    • row_heading

    • level<k> wherek is the level in a MultiIndex

    • row<m> wherem is the numeric position of the row

  • Column label cells include

    • col_heading

    • level<k> wherek is the level in a MultiIndex

    • col<n> wheren is the numeric position of the column

  • Data cells include

    • data

    • row<m>, wherem is the numeric position of the cell.

    • col<n>, wheren is the numeric position of the cell.

  • Blank cells includeblank

  • Trimmed cells includecol_trim orrow_trim

The structure of theid isT_uuid_level<k>_row<m>_col<n> wherelevel<k> is used only on headings, and headings will only have eitherrow<m> orcol<n> whichever is needed. By default 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 read more about the use of UUIDs inOptimization.

We can see example of the HTML by calling the.to_html() method.

[71]:
print(pd.DataFrame([[1,2],[3,4]],index=['i1','i2'],columns=['c1','c2']).style.to_html())
<style type="text/css"></style><table id="T_19b1e">  <thead>    <tr>      <th class="blank level0" >&nbsp;</th>      <th id="T_19b1e_level0_col0" class="col_heading level0 col0" >c1</th>      <th id="T_19b1e_level0_col1" class="col_heading level0 col1" >c2</th>    </tr>  </thead>  <tbody>    <tr>      <th id="T_19b1e_level0_row0" class="row_heading level0 row0" >i1</th>      <td id="T_19b1e_row0_col0" class="data row0 col0" >1</td>      <td id="T_19b1e_row0_col1" class="data row0 col1" >2</td>    </tr>    <tr>      <th id="T_19b1e_level0_row1" class="row_heading level0 row1" >i2</th>      <td id="T_19b1e_row1_col0" class="data row1 col0" >3</td>      <td id="T_19b1e_row1_col1" class="data row1 col1" >4</td>    </tr>  </tbody></table>

CSS Hierarchies#

The examples have shown that when CSS styles overlap, the one that comes last in the HTML render, takes precedence. So the following yield different results:

[72]:
df4=pd.DataFrame([['text']])df4.style.map(lambdax:'color:green;')\.map(lambdax:'color:red;')
[72]:
 0
0text
[73]:
df4.style.map(lambdax:'color:red;')\.map(lambdax:'color:green;')
[73]:
 0
0text

This is only true for CSS rules that are equivalent in hierarchy, or importance. You can read more aboutCSS specificity here but for our purposes it suffices to summarize the key points:

A CSS importance score for each HTML element is derived by starting at zero and adding:

  • 1000 for an inline style attribute

  • 100 for each ID

  • 10 for each attribute, class or pseudo-class

  • 1 for each element name or pseudo-element

Let’s use this to describe the action of the following configurations

[74]:
df4.style.set_uuid('a_')\.set_table_styles([{'selector':'td','props':'color:red;'}])\.map(lambdax:'color:green;')
[74]:
 0
0text

This text is red because the generated selector#T_a_td is worth 101 (ID plus element), whereas#T_a_row0_col0 is only worth 100 (ID), so is considered inferior even though in the HTML it comes after the previous.

[75]:
df4.style.set_uuid('b_')\.set_table_styles([{'selector':'td','props':'color:red;'},{'selector':'.cls-1','props':'color:blue;'}])\.map(lambdax:'color:green;')\.set_td_classes(pd.DataFrame([['cls-1']]))
[75]:
 0
0text

In the above case the text is blue because the selector#T_b_.cls-1 is worth 110 (ID plus class), which takes precedence.

[76]:
df4.style.set_uuid('c_')\.set_table_styles([{'selector':'td','props':'color:red;'},{'selector':'.cls-1','props':'color:blue;'},{'selector':'td.data','props':'color:yellow;'}])\.map(lambdax:'color:green;')\.set_td_classes(pd.DataFrame([['cls-1']]))
[76]:
 0
0text

Now we have created another table style this time the selectorT_c_td.data (ID plus element plus class) gets bumped up to 111.

If your style fails to be applied, and its really frustrating, try the!important trump card.

[77]:
df4.style.set_uuid('d_')\.set_table_styles([{'selector':'td','props':'color:red;'},{'selector':'.cls-1','props':'color:blue;'},{'selector':'td.data','props':'color:yellow;'}])\.map(lambdax:'color:green !important;')\.set_td_classes(pd.DataFrame([['cls-1']]))
[77]:
 0
0text

Finally got that green text after all!

Extensibility#

The core of pandas is, and will remain, its “high-performance, easy-to-use data structures”. With that in mind, we hope thatDataFrame.style accomplishes two goals

  • Provide an API that is pleasing to use interactively and is “good enough” for many tasks

  • Provide the foundations for dedicated libraries to build on

If you build a great library on top of this, let us know and we’lllink to it.

Subclassing#

If the default template doesn’t quite suit your needs, you can subclass Styler and extend or override the template. We’ll show an example of extending the default template to insert a custom header before each table.

[78]:
fromjinja2importEnvironment,ChoiceLoader,FileSystemLoaderfromIPython.displayimportHTMLfrompandas.io.formats.styleimportStyler

We’ll use the following template:

[79]:
withopen("templates/myhtml.tpl")asf:print(f.read())
{% extends "html_table.tpl" %}{% block table %}<h1>{{ table_title|default("My Table") }}</h1>{{ super() }}{% endblock table %}

Now that we’ve created a template, we need to set up a subclass ofStyler that knows about it.

[80]:
classMyStyler(Styler):env=Environment(loader=ChoiceLoader([FileSystemLoader("templates"),# contains oursStyler.loader,# the default]))template_html_table=env.get_template("myhtml.tpl")

Notice that we include the original loader in our environment’s loader. That’s because we extend the original template, so the Jinja environment needs to be able to find it.

Now we can use that custom styler. It’s__init__ takes a DataFrame.

[81]:
MyStyler(df3)
[81]:

My Table

  c1c2c3c4
Ar1-1.048553-1.420018-1.7062701.950775
r2-0.509652-0.438074-1.2527950.777490
Br1-1.613898-0.212740-0.8954670.386902
r2-0.510805-1.180632-0.0281820.428332

Our custom template accepts atable_title keyword. We can provide the value in the.to_html method.

[82]:
HTML(MyStyler(df3).to_html(table_title="Extending Example"))
[82]:

Extending Example

  c1c2c3c4
Ar1-1.048553-1.420018-1.7062701.950775
r2-0.509652-0.438074-1.2527950.777490
Br1-1.613898-0.212740-0.8954670.386902
r2-0.510805-1.180632-0.0281820.428332

For convenience, we provide theStyler.from_custom_template method that does the same as the custom subclass.

[83]:
EasyStyler=Styler.from_custom_template("templates","myhtml.tpl")HTML(EasyStyler(df3).to_html(table_title="Another Title"))
[83]:

Another Title

  c1c2c3c4
Ar1-1.048553-1.420018-1.7062701.950775
r2-0.509652-0.438074-1.2527950.777490
Br1-1.613898-0.212740-0.8954670.386902
r2-0.510805-1.180632-0.0281820.428332

Template Structure#

Here’s the template structure for the both the style generation template and the table generation template:

Style template:

[85]:
HTML(style_structure)
[85]:
before_style
style
<style type="text/css">
table_styles
before_cellstyle
cellstyle
</style>

Table template:

[87]:
HTML(table_structure)
[87]:
before_table
table
<table ...>
caption
thead
before_head_rows
head_tr (loop over headers)
after_head_rows
tbody
before_rows
tr (loop over data rows)
after_rows
</table>
after_table

See the template in theGitHub repo for more details.

On this page

[8]ページ先頭

©2009-2025 Movatter.jp