Skip to content

Commit 546dd1a

Browse files
committed
doc, more tests
1 parent 9a4cb55 commit 546dd1a

File tree

4 files changed

+80
-22
lines changed

4 files changed

+80
-22
lines changed

doc/python/hover-text-and-formatting.md

Lines changed: 32 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ jupyter:
66
extension: .md
77
format_name: markdown
88
format_version: '1.2'
9-
jupytext_version: 1.3.1
9+
jupytext_version: 1.4.2
1010
kernelspec:
1111
display_name: Python 3
1212
language: python
@@ -20,7 +20,7 @@ jupyter:
2020
name: python
2121
nbconvert_exporter: python
2222
pygments_lexer: ipython3
23-
version: 3.6.8
23+
version: 3.7.3
2424
plotly:
2525
description: How to use hover text and formatting in Python with Plotly.
2626
display_as: file_settings
@@ -102,7 +102,7 @@ fig.show()
102102

103103
### Customizing Hover text with Plotly Express
104104

105-
Plotly Express functions automatically add all the data being plotted (x, y, color etc) to the hover label. Many Plotly Express functions also support configurable hover text. The `hover_data` argument accepts a list of column names to be added to the hover tooltip. The `hover_name` property controls which column is displayed in bold as the tooltip title.
105+
Plotly Express functions automatically add all the data being plotted (x, y, color etc) to the hover label. Many Plotly Express functions also support configurable hover text. The `hover_data` argument accepts a list of column names to be added to the hover tooltip, or a dictionary for advanced formatting (see the next section). The `hover_name` property controls which column is displayed in bold as the tooltip title.
106106

107107
Here is an example that creates a scatter plot using Plotly Express with custom hover data and a custom hover name.
108108

@@ -117,6 +117,35 @@ fig = px.scatter(df_2007, x="gdpPercap", y="lifeExp", log_x=True,
117117
fig.show()
118118
```
119119

120+
### Disabling or customizing hover of columns in plotly express
121+
122+
`hover_data` can also be a dictionary. Its keys are existing columns of the `dataframe` argument, or new labels. For an existing column, the values can be
123+
* `False` to remove the column from the hover data (for example, if one wishes to remove the column of the `x` argument)
124+
* `True` to add a different column, with default formatting
125+
* a formatting string starting with `:` for numbers [d3-format's syntax](https://github.com/d3/d3-3.x-api-reference/blob/master/Formatting.md#d3_forma), and `|` for dates in [d3-time-format's syntax](https://github.com/d3/d3-3.x-api-reference/blob/master/Time-Formatting.md#format), for example `:.3f`, `|%a`.
126+
127+
For passing new data, the value is a tuple, which first element is one of the possible values described above for existing columns, and the second element correspond to the hover values, for example `(True, [1, 2, 3])` or `(':.1f', [1.54, 2.345])`.
128+
129+
These different cases are illustrated in the following example.
130+
131+
```python
132+
import plotly.express as px
133+
import numpy as np
134+
df = px.data.iris()
135+
fig = px.scatter(df, x='petal_length', y='sepal_length', facet_col='species', color='species',
136+
hover_data={'species':False, # remove species from hover data
137+
'sepal_length':':.2f', # customize hover for column of y attribute
138+
'petal_width':True, # add other column, default formatting
139+
'sepal_width':':.2f', # add other column, customized formatting
140+
# data not in dataframe, default formatting
141+
'suppl_1': (True, np.random.random(len(df))),
142+
# data not in dataframe, customized formatting
143+
'suppl_2': (':.3f', np.random.random(len(df)))
144+
})
145+
fig.update_layout(height=300)
146+
fig.show()
147+
```
148+
120149
### Customizing hover text with a hovertemplate
121150

122151
To customize the tooltip on your graph you can use [hovertemplate](https://plotly.com/python/reference/#pie-hovertemplate), which is a template string used for rendering the information that appear on hoverbox.

packages/python/plotly/plotly/express/_core.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -985,7 +985,7 @@ def build_dataframe(args, attrables, array_attrables):
985985
bypass_warnings = (
986986
hover_data_is_dict
987987
and argument in args["hover_data"]
988-
and args["hover_data"][argument][1]
988+
and args["hover_data"][argument][1] is not None
989989
)
990990
if not df_provided and not bypass_warnings:
991991
raise ValueError(
@@ -1022,7 +1022,7 @@ def build_dataframe(args, attrables, array_attrables):
10221022
if (
10231023
field_name == "hover_data"
10241024
and hover_data_is_dict
1025-
and args["hover_data"][col_name][1]
1025+
and args["hover_data"][col_name][1] is not None
10261026
):
10271027
df_output[col_name] = args["hover_data"][col_name][1]
10281028
else:

packages/python/plotly/plotly/express/_doc.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -185,7 +185,9 @@
185185
"or array_like objects",
186186
"or a dict with column names as keys, with values True (for default formatting)",
187187
"False (in order to remove this column from hover information),",
188-
"or a formatting string, for example ':.3f' or '|%a'."
188+
"or a formatting string, for example ':.3f' or '|%a'",
189+
"or tuples with a bool or formatting string as first element,",
190+
"and list-like data to appear in hover as second element",
189191
"Values from these columns appear as extra data in the hover tooltip.",
190192
],
191193
custom_data=[

packages/python/plotly/plotly/tests/test_core/test_px/test_px_hover.py

Lines changed: 43 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,9 @@ def test_skip_hover():
2020

2121
def test_composite_hover():
2222
df = px.data.tips()
23-
hover_dict = OrderedDict({"day": False, "sex": True, "total_bill": ":.1f"})
23+
hover_dict = OrderedDict(
24+
{"day": False, "time": False, "sex": True, "total_bill": ":.1f"}
25+
)
2426
fig = px.scatter(
2527
df,
2628
x="tip",
@@ -29,12 +31,11 @@ def test_composite_hover():
2931
facet_row="time",
3032
hover_data=hover_dict,
3133
)
32-
assert (
33-
fig.data[0].hovertemplate
34-
== "time=Dinner<br>tip=%{x}<br>total_bill=%{customdata[2]:.1f}<br>sex=%{customdata[1]}<extra></extra>"
35-
or fig.data[0].hovertemplate
36-
== "time=Dinner<br>tip=%{x}<br>total_bill=%{customdata[1]:.1f}<br>sex=%{customdata[0]}<extra></extra>"
37-
)
34+
for el in ["tip", "total_bill", "sex"]:
35+
assert el in fig.data[0].hovertemplate
36+
for el in ["day", "time"]:
37+
assert el not in fig.data[0].hovertemplate
38+
assert ":.1f" in fig.data[0].hovertemplate
3839

3940

4041
def test_tuple_hover_data():
@@ -45,12 +46,38 @@ def test_tuple_hover_data():
4546
fig.data[0].hovertemplate
4647
== "x=%{x}<br>y=%{y}<br>comment=%{customdata[0]}<extra></extra>"
4748
)
48-
fig = px.scatter(
49-
x=[1, 2, 3],
50-
y=[3, 4, 5],
51-
hover_data={"comment": (":.1f", [1.234, 45.3455, 5666.234])},
52-
)
53-
assert (
54-
fig.data[0].hovertemplate
55-
== "x=%{x}<br>y=%{y}<br>comment=%{customdata[0]:.1f}<extra></extra>"
56-
)
49+
hover_dicts = [
50+
{"comment": (":.1f", [1.234, 45.3455, 5666.234])},
51+
{"comment": (":.1f", np.array([1.234, 45.3455, 5666.234]))},
52+
{"comment": (":.1f", pd.Series([1.234, 45.3455, 5666.234]))},
53+
]
54+
for hover_dict in hover_dicts:
55+
fig = px.scatter(x=[1, 2, 3], y=[3, 4, 5], hover_data=hover_dict,)
56+
assert (
57+
fig.data[0].hovertemplate
58+
== "x=%{x}<br>y=%{y}<br>comment=%{customdata[0]:.1f}<extra></extra>"
59+
)
60+
61+
62+
def test_fail_wrong_column():
63+
with pytest.raises(ValueError):
64+
fig = px.scatter(
65+
{"a": [1, 2], "b": [3, 4], "c": [2, 1]},
66+
x="a",
67+
y="b",
68+
hover_data={"d": True},
69+
)
70+
with pytest.raises(ValueError):
71+
fig = px.scatter(
72+
{"a": [1, 2], "b": [3, 4], "c": [2, 1]},
73+
x="a",
74+
y="b",
75+
hover_data={"d": ":.1f"},
76+
)
77+
with pytest.raises(ValueError):
78+
fig = px.scatter(
79+
{"a": [1, 2], "b": [3, 4], "c": [2, 1]},
80+
x="a",
81+
y="b",
82+
hover_data={"d": (True, [3, 4, 5])},
83+
)

0 commit comments

Comments
 (0)