Skip to content

Commit 6449e27

Browse files
Coding-with-Adamnicolaskruchten
authored andcommitted
docs(icicle): complete icicle with PX examples; proof-read the copy
1 parent e7267bc commit 6449e27

File tree

1 file changed

+123
-26
lines changed

1 file changed

+123
-26
lines changed

doc/python/icicle-charts.md

+123-26
Original file line numberDiff line numberDiff line change
@@ -27,13 +27,13 @@ jupyter:
2727
language: python
2828
layout: base
2929
name: Icicle Charts
30-
order: 10
30+
order: 13.5
3131
page_type: u-guide
3232
permalink: python/icicle-charts/
33-
thumbnail: thumbnail/icicle.gif
33+
thumbnail: thumbnail/icicle.png
3434
---
3535

36-
Similar to Treemap plots and Icicle plots, Icicle plots provide yet another way to visualize hierarchical data. Children are drawn next to their parent boxes, all on one side (eg. each on the right side of their parent). Icicle plots can point in one of four directions (left, right, top, bottom); this direction is acheived with the `tiling` sub-attributes `orientation` and `flip`.
36+
Icicle charts visualize hierarchical data using rectangular sectors that cascade from root to leaves in one of four directions: up, down, left, or right. Similar to [Sunburst](https://plotly.com/python/sunburst-charts/) and [Treemap](https://plotly.com/python/treemaps/) charts, the hierarchy is defined by `labels` (`names` for `px.icicle`) and `parents` attributes. Click on one sector to zoom in/out, which also displays a pathbar on the top of your icicle. To zoom out, you can click the parent sector or click the pathbar as well.
3737

3838
Main arguments:
3939

@@ -43,16 +43,106 @@ Main arguments:
4343

4444
### Basic Icicle Plot with plotly.express
4545

46+
[Plotly Express](/python/plotly-express/) is the easy-to-use, high-level interface to Plotly, which [operates on a variety of types of data](/python/px-arguments/) and produces [easy-to-style figures](/python/styling-plotly-express/).
47+
48+
With `px.icicle`, each item in the `character` list is represented as a rectangular sector of the icicle.
49+
50+
```python
51+
import plotly.express as px
52+
data = dict(
53+
character=["Eve", "Cain", "Seth", "Enos", "Noam", "Abel", "Awan", "Enoch", "Azura"],
54+
parent=["", "Eve", "Eve", "Seth", "Seth", "Eve", "Eve", "Awan", "Eve" ],
55+
value=[10, 14, 12, 10, 2, 6, 6, 4, 4])
56+
57+
fig =px.icicle(
58+
data,
59+
names='character',
60+
parents='parent',
61+
values='value',
62+
)
63+
fig.show()
64+
```
65+
4666
### Icicle of a rectangular DataFrame with plotly.express
4767

68+
Hierarchical data are often stored as a rectangular dataframe, with different columns corresponding to different levels of the hierarchy. `px.icicle` can take a path parameter corresponding to a list of columns. Note that `id` and `parent` should not be provided if path is given.
69+
70+
71+
```python
72+
import plotly.express as px
73+
df = px.data.tips()
74+
fig = px.icicle(df, path=['day', 'time', 'sex'], values='total_bill')
75+
fig.show()
76+
```
77+
4878
### Icicle of a rectangular DataFrame with continuous color argument in px.icicle
4979

80+
If a color argument is passed, the color of a node is computed as the average of the color values of its children, weighted by their values.
81+
82+
```python
83+
import plotly.express as px
84+
import numpy as np
85+
df = px.data.gapminder().query("year == 2007")
86+
fig = px.icicle(df, path=['continent', 'country'], values='pop',
87+
color='lifeExp', hover_data=['iso_alpha'],
88+
color_continuous_scale='RdBu',
89+
color_continuous_midpoint=np.average(df['lifeExp'], weights=df['pop']))
90+
fig.show()
91+
```
92+
5093
### Icicle of a rectangular DataFrame with discrete color argument in px.icicle
5194

95+
When the argument of color corresponds to non-numerical data, discrete colors are used. If a sector has the same value of the color column for all its children, then the corresponding color is used, otherwise the first color of the discrete color sequence is used.
96+
97+
```python
98+
import plotly.express as px
99+
df = px.data.tips()
100+
fig = px.icicle(df, path=['sex', 'day', 'time'], values='total_bill', color='day')
101+
fig.show()
102+
```
103+
104+
In the example below the color of **Saturday** and **Sunday** sectors is the same as **Dinner** because there are only Dinner entries for Saturday and Sunday. However, for Female -> Friday there are both lunches and dinners, hence the "mixed" color (blue here) is used.
105+
106+
```python
107+
import plotly.express as px
108+
df = px.data.tips()
109+
fig = px.icicle(df, path=['sex', 'day', 'time'], values='total_bill', color='time')
110+
fig.show()
111+
```
112+
52113
### Using an explicit mapping for discrete colors
53114

115+
For more information about discrete colors, see the [dedicated page](https://plotly.com/python/discrete-color/).
116+
117+
```python
118+
import plotly.express as px
119+
df = px.data.tips()
120+
fig = px.icicle(df, path=['sex', 'day', 'time'], values='total_bill', color='time',
121+
color_discrete_map={'(?)':'black', 'Lunch':'gold', 'Dinner':'darkblue'})
122+
fig.show()
123+
```
124+
54125
### Rectangular data with missing values
55126

127+
If the dataset is not fully rectangular, missing values should be supplied as **None**. Note that the parents of **None** entries must be a leaf, i.e. it cannot have other children than **None** (otherwise a **ValueError** is raised).
128+
129+
```python
130+
import plotly.express as px
131+
import pandas as pd
132+
vendors = ["A", "B", "C", "D", None, "E", "F", "G", "H", None]
133+
sectors = ["Tech", "Tech", "Finance", "Finance", "Other",
134+
"Tech", "Tech", "Finance", "Finance", "Other"]
135+
regions = ["North", "North", "North", "North", "North",
136+
"South", "South", "South", "South", "South"]
137+
sales = [1, 3, 2, 4, 1, 2, 2, 1, 4, 1]
138+
df = pd.DataFrame(
139+
dict(vendors=vendors, sectors=sectors, regions=regions, sales=sales)
140+
)
141+
print(df)
142+
fig = px.icicle(df, path=['regions', 'sectors', 'vendors'], values='sales')
143+
fig.show()
144+
```
145+
56146
### Basic Icicle Plot with go.Icicle
57147

58148
If Plotly Express does not provide a good starting point, it is also possible to use [the more generic `go.Icicle` class from `plotly.graph_objects`](/python/graph-objects/).
@@ -198,7 +288,7 @@ value_column = 'calls'
198288

199289
def build_hierarchical_dataframe(df, levels, value_column, color_columns=None):
200290
"""
201-
Build a hierarchy of levels for Icicle or Treemap charts.
291+
Build a hierarchy of levels for Icicle charts.
202292
203293
Levels are given starting from the bottom to the top of the hierarchy,
204294
ie the last level corresponds to the root.
@@ -274,20 +364,20 @@ fig = go.Figure(go.Icicle(
274364
fig.show()
275365
```
276366

277-
This example uses treemapcolorway attribute, which should be set in layout.
367+
This example uses iciclecolorway attribute, which should be set in layout.
278368

279369
```python
280370
import plotly.graph_objects as go
281371

282372
labels = ["A1", "A2", "A3", "A4", "A5", "B1", "B2"]
283373
parents = ["", "A1", "A2", "A3", "A4", "", "B1"]
284374

285-
fig = go.Figure(go.Treemap(
375+
fig = go.Figure(go.Icicle(
286376
labels = labels,
287377
parents = parents
288378
))
289379

290-
fig.update_layout(treemapcolorway = ["pink", "lightgray"])
380+
fig.update_layout(iciclecolorway = ["pink", "lightgray"])
291381

292382
fig.show()
293383
```
@@ -299,7 +389,7 @@ values = ["11", "12", "13", "14", "15", "20", "30"]
299389
labels = ["A1", "A2", "A3", "A4", "A5", "B1", "B2"]
300390
parents = ["", "A1", "A2", "A3", "A4", "", "B1"]
301391

302-
fig = go.Figure(go.Treemap(
392+
fig = go.Figure(go.Icicle(
303393
labels = labels,
304394
values = values,
305395
parents = parents,
@@ -314,9 +404,10 @@ As mentioned above, Icicle charts can grow in one of four directions. Icicle cha
314404

315405
NB. A "flame chart" refers to an Icicle chart that is pointing upwards.
316406

317-
Up
407+
**Up Direction**
318408

319409
```python
410+
import plotly.graph_objects as go
320411
import pandas as pd
321412

322413
df = pd.read_csv('https://raw.githubusercontent.com/plotly/datasets/718417069ead87650b90472464c7565dc8c2cb1c/sunburst-coffee-flavors-complete.csv')
@@ -339,9 +430,10 @@ fig.update_layout(
339430
fig.show()
340431
```
341432

342-
Down
433+
**Down Direction**
343434

344435
```python
436+
import plotly.graph_objects as go
345437
import pandas as pd
346438

347439
df = pd.read_csv('https://raw.githubusercontent.com/plotly/datasets/718417069ead87650b90472464c7565dc8c2cb1c/sunburst-coffee-flavors-complete.csv')
@@ -363,9 +455,10 @@ fig.update_layout(
363455
fig.show()
364456
```
365457

366-
Right
458+
**Right Direction**
367459

368460
```python
461+
import plotly.graph_objects as go
369462
import pandas as pd
370463

371464
df = pd.read_csv('https://raw.githubusercontent.com/plotly/datasets/718417069ead87650b90472464c7565dc8c2cb1c/sunburst-coffee-flavors-complete.csv')
@@ -387,9 +480,10 @@ fig.update_layout(
387480
fig.show()
388481
```
389482

390-
Left
483+
**Left Direction**
391484

392485
```python
486+
import plotly.graph_objects as go
393487
import pandas as pd
394488

395489
df = pd.read_csv('https://raw.githubusercontent.com/plotly/datasets/718417069ead87650b90472464c7565dc8c2cb1c/sunburst-coffee-flavors-complete.csv')
@@ -414,26 +508,25 @@ fig.show()
414508

415509
### Pad
416510

417-
Similar to [treemaps](https://plotly.com/python/treemaps/), the space between each Icicle slice can be set with `pad`, a sub-attribute of the `tiling` attribute.
511+
Similar to [treemaps](https://plotly.com/python/treemaps/), the space between each Icicle slice can be set with `pad`, one of the sub-attributes of the `tiling` attribute.
418512

419513

420514
```python
421515
import plotly.graph_objs as go
422516
from plotly.subplots import make_subplots
423-
424517
import pandas as pd
425518

426519
df1 = pd.read_csv('https://raw.githubusercontent.com/plotly/datasets/718417069ead87650b90472464c7565dc8c2cb1c/sunburst-coffee-flavors-complete.csv')
427520

428-
pad_vals = [0, 2, 4, 8]
521+
pad_values = [0, 2, 4, 6]
429522
num_of_cols = 4
430523

431524
fig = make_subplots(
432525
rows = 1, cols = 4,
433-
column_titles=[f'pad: {pad_vals[i]}' for i in range(num_of_cols)],
526+
column_titles=[f'pad: {pad_values[i]}' for i in range(num_of_cols)],
434527
specs = [
435528
[
436-
{'type': 'icicle', 'rowspan': 1} for i in range(num_of_cols)
529+
dict(type = 'icicle', rowspan = 1) for i in range(num_of_cols)
437530
]
438531
]
439532
)
@@ -443,9 +536,10 @@ fig.add_trace(
443536
ids = df1.ids,
444537
labels = df1.labels,
445538
parents = df1.parents,
446-
root = dict( color = "DodgerBlue" ),
539+
pathbar = dict(side = 'bottom'),
540+
root = dict(color = 'DodgerBlue'),
447541
tiling = dict(
448-
pad = pad_vals[0]
542+
pad = pad_values[0]
449543
)
450544
),
451545
col = 1,
@@ -457,9 +551,10 @@ fig.add_trace(
457551
ids = df1.ids,
458552
labels = df1.labels,
459553
parents = df1.parents,
460-
root = dict( color = "DodgerBlue" ),
554+
pathbar = dict(side = 'bottom'),
555+
root = dict(color = 'DodgerBlue'),
461556
tiling = dict(
462-
pad = pad_vals[1]
557+
pad = pad_values[1]
463558
)
464559
),
465560
col = 2,
@@ -471,9 +566,10 @@ fig.add_trace(
471566
ids = df1.ids,
472567
labels = df1.labels,
473568
parents = df1.parents,
474-
root = dict( color = "DodgerBlue" ),
569+
pathbar = dict(side = 'bottom'),
570+
root = dict(color = 'DodgerBlue'),
475571
tiling = dict(
476-
pad = pad_vals[2]
572+
pad = pad_values[2]
477573
)
478574
),
479575
col = 3,
@@ -485,17 +581,18 @@ fig.add_trace(
485581
ids = df1.ids,
486582
labels = df1.labels,
487583
parents = df1.parents,
488-
root = dict( color = "DodgerBlue" ),
584+
pathbar = dict(side = 'bottom'),
585+
root = dict(color = 'DodgerBlue'),
489586
tiling = dict(
490-
pad = pad_vals[3]
587+
pad = pad_values[3]
491588
)
492589
),
493590
col = 4,
494591
row = 1
495592
)
496593

497594
fig.update_layout(
498-
margin = {'l':0, 'r':0, 'b':0},
595+
margin = dict(l=0, r=0)
499596
)
500597

501598
fig.show()

0 commit comments

Comments
 (0)