Skip to content

Commit 2f44bf8

Browse files
committed
tuple possible in hover_data dict
1 parent e3ec1e2 commit 2f44bf8

File tree

2 files changed

+51
-9
lines changed

2 files changed

+51
-9
lines changed

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

Lines changed: 30 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -396,10 +396,10 @@ def make_trace_kwargs(args, trace_spec, trace_data, mapping_labels, sizeref):
396396
if args["hover_data"] and isinstance(args["hover_data"], dict):
397397
for k, v in mapping_labels.items():
398398
if k in args["hover_data"]:
399-
if args["hover_data"][k]:
400-
if isinstance(args["hover_data"][k], str):
399+
if args["hover_data"][k][0]:
400+
if isinstance(args["hover_data"][k][0], str):
401401
mapping_labels_copy[k] = v.replace(
402-
"}", "%s}" % args["hover_data"][k]
402+
"}", "%s}" % args["hover_data"][k][0]
403403
)
404404
else:
405405
_ = mapping_labels_copy.pop(k)
@@ -935,6 +935,17 @@ def build_dataframe(args, attrables, array_attrables):
935935
else:
936936
df_output[df_input.columns] = df_input[df_input.columns]
937937

938+
# hover_data is a dict
939+
hover_data_is_dict = (
940+
"hover_data" in args
941+
and args["hover_data"]
942+
and isinstance(args["hover_data"], dict)
943+
)
944+
if hover_data_is_dict:
945+
for k in args["hover_data"]:
946+
if not isinstance(args["hover_data"][k], tuple):
947+
args["hover_data"][k] = (args["hover_data"][k], None)
948+
938949
# Loop over possible arguments
939950
for field_name in attrables:
940951
# Massaging variables
@@ -970,15 +981,20 @@ def build_dataframe(args, attrables, array_attrables):
970981
if isinstance(argument, str) or isinstance(
971982
argument, int
972983
): # just a column name given as str or int
973-
if not df_provided:
984+
bypass_warnings = (
985+
hover_data_is_dict
986+
and argument in args["hover_data"]
987+
and args["hover_data"][argument][1]
988+
)
989+
if not df_provided and not bypass_warnings:
974990
raise ValueError(
975991
"String or int arguments are only possible when a "
976992
"DataFrame or an array is provided in the `data_frame` "
977993
"argument. No DataFrame was provided, but argument "
978994
"'%s' is of type str or int." % field
979995
)
980996
# Check validity of column name
981-
if argument not in df_input.columns:
997+
if not bypass_warnings and argument not in df_input.columns:
982998
err_msg = (
983999
"Value of '%s' is not the name of a column in 'data_frame'. "
9841000
"Expected one of %s but received: %s"
@@ -989,7 +1005,7 @@ def build_dataframe(args, attrables, array_attrables):
9891005
"\n To use the index, pass it in directly as `df.index`."
9901006
)
9911007
raise ValueError(err_msg)
992-
if length and len(df_input[argument]) != length:
1008+
if not bypass_warnings and length and len(df_input[argument]) != length:
9931009
raise ValueError(
9941010
"All arguments should have the same length. "
9951011
"The length of column argument `df[%s]` is %d, whereas the "
@@ -1002,7 +1018,14 @@ def build_dataframe(args, attrables, array_attrables):
10021018
)
10031019
)
10041020
col_name = str(argument)
1005-
df_output[col_name] = df_input[argument].values
1021+
if (
1022+
field_name == "hover_data"
1023+
and hover_data_is_dict
1024+
and args["hover_data"][col_name][1]
1025+
):
1026+
df_output[col_name] = args["hover_data"][col_name][1]
1027+
else:
1028+
df_output[col_name] = df_input[argument].values
10061029
# ----------------- argument is a column / array / list.... -------
10071030
else:
10081031
is_index = isinstance(argument, pd.RangeIndex)

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

Lines changed: 21 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ def test_skip_hover():
2121
def test_composite_hover():
2222
df = px.data.tips()
2323
hover_dict = OrderedDict(
24-
{"day": False, "sex": True, "time": False, "total_bill": ":.1f"}
24+
{"day": False, "sex": True, "time": False, "total_bill": ":.1f"}
2525
)
2626
fig = px.scatter(
2727
df,
@@ -33,5 +33,24 @@ def test_composite_hover():
3333
)
3434
assert (
3535
fig.data[0].hovertemplate
36-
== "tip=%{x}<br>total_bill=%{customdata[1]:.1f}<br>sex=%{customdata[0]}<extra></extra>"
36+
== "tip=%{x}<br>total_bill=%{customdata[3]:.1f}<br>sex=%{customdata[1]}<extra></extra>"
37+
)
38+
39+
40+
def test_tuple_hover_data():
41+
fig = px.scatter(
42+
x=[1, 2, 3], y=[3, 4, 5], hover_data={"comment": (True, ["a", "b", "c"])}
43+
)
44+
assert (
45+
fig.data[0].hovertemplate
46+
== "x=%{x}<br>y=%{y}<br>comment=%{customdata[0]}<extra></extra>"
47+
)
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>"
3756
)

0 commit comments

Comments
 (0)