Skip to content

Commit 4510c6f

Browse files
attack68mroeschke
andauthored
DOC: update style.ipynb for 2.0 (#50973)
* update style.ipynb for 2.0 * Update doc/source/user_guide/style.ipynb * Update doc/source/user_guide/style.ipynb Co-authored-by: Matthew Roeschke <[email protected]> * Update doc/source/user_guide/style.ipynb Co-authored-by: Matthew Roeschke <[email protected]> * Update doc/source/user_guide/style.ipynb Co-authored-by: Matthew Roeschke <[email protected]> * ensure imports at top of file --------- Co-authored-by: JHM Darbyshire (iMac) <[email protected]> Co-authored-by: Matthew Roeschke <[email protected]>
1 parent 3e8c3b0 commit 4510c6f

File tree

1 file changed

+188
-104
lines changed

1 file changed

+188
-104
lines changed

doc/source/user_guide/style.ipynb

+188-104
Original file line numberDiff line numberDiff line change
@@ -9,23 +9,33 @@
99
"This section demonstrates visualization of tabular data using the [Styler][styler]\n",
1010
"class. For information on visualization with charting please see [Chart Visualization][viz]. This document is written as a Jupyter Notebook, and can be viewed or downloaded [here][download].\n",
1111
"\n",
12-
"[styler]: ../reference/api/pandas.io.formats.style.Styler.rst\n",
13-
"[viz]: visualization.rst\n",
14-
"[download]: https://nbviewer.ipython.org/github/pandas-dev/pandas/blob/main/doc/source/user_guide/style.ipynb"
15-
]
16-
},
17-
{
18-
"cell_type": "markdown",
19-
"metadata": {},
20-
"source": [
21-
"## Styler Object and HTML \n",
12+
"## Styler Object and Customising the Display\n",
13+
"Styling and output display customisation should be performed **after** the data in a DataFrame has been processed. The Styler is **not** dynamically updated if further changes to the DataFrame are made. The `DataFrame.style` attribute is a property that returns a [Styler][styler] object. It has a `_repr_html_` method defined on it so it is rendered automatically in Jupyter Notebook.\n",
2214
"\n",
23-
"Styling should be performed after the data in a DataFrame has been processed. The [Styler][styler] creates an HTML `<table>` and leverages CSS styling language to manipulate many parameters including colors, fonts, borders, background, etc. See [here][w3schools] for more information on styling HTML tables. This allows a lot of flexibility out of the box, and even enables web developers to integrate DataFrames into their exiting user interface designs.\n",
24-
" \n",
25-
"The `DataFrame.style` attribute is a property that returns a [Styler][styler] object. It has a `_repr_html_` method defined on it so they are rendered automatically in Jupyter Notebook.\n",
15+
"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:\n",
16+
"\n",
17+
" - HTML\n",
18+
" - LaTeX\n",
19+
" - String (and CSV by extension)\n",
20+
" - Excel\n",
21+
" - (JSON is not currently available)\n",
22+
"\n",
23+
"The first three of these have display customisation methods designed to format and customise the output. These include:\n",
2624
"\n",
25+
" - Formatting values, the index and columns headers, using [.format()][formatfunc] and [.format_index()][formatfuncindex],\n",
26+
" - Renaming the index or column header labels, using [.relabel_index()][relabelfunc]\n",
27+
" - Hiding certain columns, the index and/or column headers, or index names, using [.hide()][hidefunc]\n",
28+
" - Concatenating similar DataFrames, using [.concat()][concatfunc]\n",
29+
" \n",
2730
"[styler]: ../reference/api/pandas.io.formats.style.Styler.rst\n",
28-
"[w3schools]: https://www.w3schools.com/html/html_tables.asp"
31+
"[viz]: visualization.rst\n",
32+
"[download]: https://nbviewer.ipython.org/github/pandas-dev/pandas/blob/main/doc/source/user_guide/style.ipynb\n",
33+
"[format]: https://docs.python.org/3/library/string.html#format-specification-mini-language\n",
34+
"[formatfunc]: ../reference/api/pandas.io.formats.style.Styler.format.rst\n",
35+
"[formatfuncindex]: ../reference/api/pandas.io.formats.style.Styler.format_index.rst\n",
36+
"[relabelfunc]: ../reference/api/pandas.io.formats.style.Styler.relabel_index.rst\n",
37+
"[hidefunc]: ../reference/api/pandas.io.formats.style.Styler.hide.rst\n",
38+
"[concatfunc]: ../reference/api/pandas.io.formats.style.Styler.concat.rst"
2939
]
3040
},
3141
{
@@ -41,6 +51,25 @@
4151
"# This cell is hidden from the output"
4252
]
4353
},
54+
{
55+
"cell_type": "markdown",
56+
"metadata": {},
57+
"source": [
58+
"## Formatting the Display\n",
59+
"\n",
60+
"### Formatting Values\n",
61+
"\n",
62+
"The [Styler][styler] distinguishes the *display* value from the *actual* value, in both data values and index or columns headers. To control the display value, the text is printed in each cell as string, and we can use the [.format()][formatfunc] and [.format_index()][formatfuncindex] methods to manipulate this according to a [format spec string][format] 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\n",
63+
"\n",
64+
"Additionally, the format function has a **precision** argument to specifically help formatting floats, as well as **decimal** and **thousands** separators to support other locales, an **na_rep** argument to display missing data, and an **escape** and **hyperlinks** arguments to help displaying safe-HTML or safe-LaTeX. The default formatter is configured to adopt pandas' global options such as `styler.format.precision` option, controllable using `with pd.option_context('format.precision', 2):` \n",
65+
"\n",
66+
"[styler]: ../reference/api/pandas.io.formats.style.Styler.rst\n",
67+
"[format]: https://docs.python.org/3/library/string.html#format-specification-mini-language\n",
68+
"[formatfunc]: ../reference/api/pandas.io.formats.style.Styler.format.rst\n",
69+
"[formatfuncindex]: ../reference/api/pandas.io.formats.style.Styler.format_index.rst\n",
70+
"[relabelfunc]: ../reference/api/pandas.io.formats.style.Styler.relabel_index.rst"
71+
]
72+
},
4473
{
4574
"cell_type": "code",
4675
"execution_count": null,
@@ -51,19 +80,157 @@
5180
"import numpy as np\n",
5281
"import matplotlib as mpl\n",
5382
"\n",
54-
"df = pd.DataFrame([[38.0, 2.0, 18.0, 22.0, 21, np.nan],[19, 439, 6, 452, 226,232]], \n",
55-
" index=pd.Index(['Tumour (Positive)', 'Non-Tumour (Negative)'], name='Actual Label:'), \n",
56-
" columns=pd.MultiIndex.from_product([['Decision Tree', 'Regression', 'Random'],['Tumour', 'Non-Tumour']], names=['Model:', 'Predicted:']))\n",
57-
"df.style"
83+
"df = pd.DataFrame({\n",
84+
" \"strings\": [\"Adam\", \"Mike\"],\n",
85+
" \"ints\": [1, 3],\n",
86+
" \"floats\": [1.123, 1000.23]\n",
87+
"})\n",
88+
"df.style \\\n",
89+
" .format(precision=3, thousands=\".\", decimal=\",\") \\\n",
90+
" .format_index(str.upper, axis=1) \\\n",
91+
" .relabel_index([\"row 1\", \"row 2\"], axis=0)"
5892
]
5993
},
6094
{
6195
"cell_type": "markdown",
6296
"metadata": {},
6397
"source": [
64-
"The above output 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()][tohtml] method, which returns the raw HTML as string, which is useful for further processing or adding to a file - read on in [More about CSS and HTML](#More-About-CSS-and-HTML). Below we will show how we can use these to format the DataFrame to be more communicative. For example how we can build `s`:\n",
98+
"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."
99+
]
100+
},
101+
{
102+
"cell_type": "code",
103+
"execution_count": null,
104+
"metadata": {},
105+
"outputs": [],
106+
"source": [
107+
"weather_df = pd.DataFrame(np.random.rand(10,2)*5, \n",
108+
" index=pd.date_range(start=\"2021-01-01\", periods=10),\n",
109+
" columns=[\"Tokyo\", \"Beijing\"])\n",
65110
"\n",
66-
"[tohtml]: ../reference/api/pandas.io.formats.style.Styler.to_html.rst"
111+
"def rain_condition(v): \n",
112+
" if v < 1.75:\n",
113+
" return \"Dry\"\n",
114+
" elif v < 2.75:\n",
115+
" return \"Rain\"\n",
116+
" return \"Heavy Rain\"\n",
117+
"\n",
118+
"def make_pretty(styler):\n",
119+
" styler.set_caption(\"Weather Conditions\")\n",
120+
" styler.format(rain_condition)\n",
121+
" styler.format_index(lambda v: v.strftime(\"%A\"))\n",
122+
" styler.background_gradient(axis=None, vmin=1, vmax=5, cmap=\"YlGnBu\")\n",
123+
" return styler\n",
124+
"\n",
125+
"weather_df"
126+
]
127+
},
128+
{
129+
"cell_type": "code",
130+
"execution_count": null,
131+
"metadata": {},
132+
"outputs": [],
133+
"source": [
134+
"weather_df.loc[\"2021-01-04\":\"2021-01-08\"].style.pipe(make_pretty)"
135+
]
136+
},
137+
{
138+
"cell_type": "markdown",
139+
"metadata": {},
140+
"source": [
141+
"### Hiding Data\n",
142+
"\n",
143+
"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.\n",
144+
"\n",
145+
"The index can be hidden from rendering by calling [.hide()][hideidx] without any arguments, which might be useful if your index is integer based. Similarly column headers can be hidden by calling [.hide(axis=\"columns\")][hideidx] without any further arguments.\n",
146+
"\n",
147+
"Specific rows or columns can be hidden from rendering by calling the same [.hide()][hideidx] method and passing in a row/column label, a list-like or a slice of row/column labels to for the ``subset`` argument.\n",
148+
"\n",
149+
"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 at `col2`, since `col0` and `col1` are simply ignored.\n",
150+
"\n",
151+
"[hideidx]: ../reference/api/pandas.io.formats.style.Styler.hide.rst"
152+
]
153+
},
154+
{
155+
"cell_type": "code",
156+
"execution_count": null,
157+
"metadata": {},
158+
"outputs": [],
159+
"source": [
160+
"df = pd.DataFrame(np.random.randn(5, 5))\n",
161+
"df.style \\\n",
162+
" .hide(subset=[0, 2, 4], axis=0) \\\n",
163+
" .hide(subset=[0, 2, 4], axis=1)"
164+
]
165+
},
166+
{
167+
"cell_type": "markdown",
168+
"metadata": {},
169+
"source": [
170+
"To invert the function to a **show** functionality it is best practice to compose a list of hidden items."
171+
]
172+
},
173+
{
174+
"cell_type": "code",
175+
"execution_count": null,
176+
"metadata": {},
177+
"outputs": [],
178+
"source": [
179+
"show = [0, 2, 4]\n",
180+
"df.style \\\n",
181+
" .hide([row for row in df.index if row not in show], axis=0) \\\n",
182+
" .hide([col for col in df.columns if col not in show], axis=1)"
183+
]
184+
},
185+
{
186+
"cell_type": "markdown",
187+
"metadata": {},
188+
"source": [
189+
"### Concatenating DataFrame Outputs\n",
190+
"\n",
191+
"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.\n",
192+
"\n",
193+
"Since the objects concatenated are Stylers they can independently be styled as will be shown below and their concatenation preserves those styles."
194+
]
195+
},
196+
{
197+
"cell_type": "code",
198+
"execution_count": null,
199+
"metadata": {},
200+
"outputs": [],
201+
"source": [
202+
"summary_styler = df.agg([\"sum\", \"mean\"]).style \\\n",
203+
" .format(precision=3) \\\n",
204+
" .relabel_index([\"Sum\", \"Average\"])\n",
205+
"df.style.format(precision=1).concat(summary_styler)"
206+
]
207+
},
208+
{
209+
"cell_type": "markdown",
210+
"metadata": {},
211+
"source": [
212+
"## Styler Object and HTML \n",
213+
"\n",
214+
"The [Styler][styler] 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. See [here][w3schools] for more information on styling HTML tables. This allows a lot of flexibility out of the box, and even enables web developers to integrate DataFrames into their exiting user interface designs.\n",
215+
"\n",
216+
"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()][tohtml] method, which returns the raw HTML as string, which is useful for further processing or adding to a file - read on in [More about CSS and HTML](#More-About-CSS-and-HTML). 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 build `s`:\n",
217+
"\n",
218+
"[tohtml]: ../reference/api/pandas.io.formats.style.Styler.to_html.rst\n",
219+
"\n",
220+
"[styler]: ../reference/api/pandas.io.formats.style.Styler.rst\n",
221+
"[w3schools]: https://www.w3schools.com/html/html_tables.asp"
222+
]
223+
},
224+
{
225+
"cell_type": "code",
226+
"execution_count": null,
227+
"metadata": {},
228+
"outputs": [],
229+
"source": [
230+
"df = pd.DataFrame([[38.0, 2.0, 18.0, 22.0, 21, np.nan],[19, 439, 6, 452, 226,232]], \n",
231+
" index=pd.Index(['Tumour (Positive)', 'Non-Tumour (Negative)'], name='Actual Label:'), \n",
232+
" columns=pd.MultiIndex.from_product([['Decision Tree', 'Regression', 'Random'],['Tumour', 'Non-Tumour']], names=['Model:', 'Predicted:']))\n",
233+
"df.style"
67234
]
68235
},
69236
{
@@ -147,90 +314,7 @@
147314
"cell_type": "markdown",
148315
"metadata": {},
149316
"source": [
150-
"## Formatting the Display\n",
151-
"\n",
152-
"### Formatting Values\n",
153-
"\n",
154-
"Before adding styles it is useful to show that the [Styler][styler] can distinguish the *display* value from the *actual* value, in both datavalues and index or columns headers. To control the display value, the text is printed in each cell as string, and we can use the [.format()][formatfunc] and [.format_index()][formatfuncindex] methods to manipulate this according to a [format spec string][format] 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. \n",
155-
"\n",
156-
"Additionally, the format function has a **precision** argument to specifically help formatting floats, as well as **decimal** and **thousands** separators to support other locales, an **na_rep** argument to display missing data, and an **escape** argument to help displaying safe-HTML or safe-LaTeX. The default formatter is configured to adopt pandas' `styler.format.precision` option, controllable using `with pd.option_context('format.precision', 2):` \n",
157-
"\n",
158-
"[styler]: ../reference/api/pandas.io.formats.style.Styler.rst\n",
159-
"[format]: https://docs.python.org/3/library/string.html#format-specification-mini-language\n",
160-
"[formatfunc]: ../reference/api/pandas.io.formats.style.Styler.format.rst\n",
161-
"[formatfuncindex]: ../reference/api/pandas.io.formats.style.Styler.format_index.rst"
162-
]
163-
},
164-
{
165-
"cell_type": "code",
166-
"execution_count": null,
167-
"metadata": {},
168-
"outputs": [],
169-
"source": [
170-
"df.style.format(precision=0, na_rep='MISSING', thousands=\" \",\n",
171-
" formatter={('Decision Tree', 'Tumour'): \"{:.2f}\",\n",
172-
" ('Regression', 'Non-Tumour'): lambda x: \"$ {:,.1f}\".format(x*-1e6)\n",
173-
" })"
174-
]
175-
},
176-
{
177-
"cell_type": "markdown",
178-
"metadata": {},
179-
"source": [
180-
"Using Styler to manipulate the display is a useful feature because maintaining the indexing and datavalues for other purposes gives greater control. You do not have to overwrite your DataFrame to display it how you like. Here is an example of using the formatting functions whilst still relying on the underlying data for indexing and calculations."
181-
]
182-
},
183-
{
184-
"cell_type": "code",
185-
"execution_count": null,
186-
"metadata": {},
187-
"outputs": [],
188-
"source": [
189-
"weather_df = pd.DataFrame(np.random.rand(10,2)*5, \n",
190-
" index=pd.date_range(start=\"2021-01-01\", periods=10),\n",
191-
" columns=[\"Tokyo\", \"Beijing\"])\n",
192-
"\n",
193-
"def rain_condition(v): \n",
194-
" if v < 1.75:\n",
195-
" return \"Dry\"\n",
196-
" elif v < 2.75:\n",
197-
" return \"Rain\"\n",
198-
" return \"Heavy Rain\"\n",
199-
"\n",
200-
"def make_pretty(styler):\n",
201-
" styler.set_caption(\"Weather Conditions\")\n",
202-
" styler.format(rain_condition)\n",
203-
" styler.format_index(lambda v: v.strftime(\"%A\"))\n",
204-
" styler.background_gradient(axis=None, vmin=1, vmax=5, cmap=\"YlGnBu\")\n",
205-
" return styler\n",
206-
"\n",
207-
"weather_df"
208-
]
209-
},
210-
{
211-
"cell_type": "code",
212-
"execution_count": null,
213-
"metadata": {},
214-
"outputs": [],
215-
"source": [
216-
"weather_df.loc[\"2021-01-04\":\"2021-01-08\"].style.pipe(make_pretty)"
217-
]
218-
},
219-
{
220-
"cell_type": "markdown",
221-
"metadata": {},
222-
"source": [
223-
"### Hiding Data\n",
224-
"\n",
225-
"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.\n",
226-
"\n",
227-
"The index can be hidden from rendering by calling [.hide()][hideidx] without any arguments, which might be useful if your index is integer based. Similarly column headers can be hidden by calling [.hide(axis=\"columns\")][hideidx] without any further arguments.\n",
228-
"\n",
229-
"Specific rows or columns can be hidden from rendering by calling the same [.hide()][hideidx] method and passing in a row/column label, a list-like or a slice of row/column labels to for the ``subset`` argument.\n",
230-
"\n",
231-
"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 at `col2`, since `col0` and `col1` are simply ignored.\n",
232-
"\n",
233-
"We can update our `Styler` object from before to hide some data and format the values.\n",
317+
"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()][hideidx].\n",
234318
"\n",
235319
"[hideidx]: ../reference/api/pandas.io.formats.style.Styler.hide.rst"
236320
]

0 commit comments

Comments
 (0)