如何自定义悬停模板以显示哪些信息

38

这是我的数据集:

my demo dataset

在按锁定数据帧并按分组后,我继续计算百分比增加/减少作为新列;最终看起来像这样:

printing 3 dfs

现在对于我的Plotly图,我使用以下代码来显示 traces 并添加一些 hover 信息:

fig.add_trace(go.Scatter(x=group_dfff.Months, y=group_dfff.Amount, name=i,
                        hovertemplate='Price: $%{y:.2f}'+'<br>Week: %{x}'))

现在你可以看到有一个参数hovertemplate,我可以传递我的x和y...不过,我无法弄清楚如何在其中也包含我的PERC_CHANGE值。

问题:如何在hovertemplate中包含其他想要的列的值?具体来说,如何将PERC_CHANGE值包含在所需的输出中,如下所示:

desired hover template output

我解决了我的具体问题,请查看下面的图片(添加第三个元素,详见评论),但问题仍然存在,因为我不知道如何为第四个、第五个等元素做到这一点。 在此输入图像描述


3
所以我针对这种特定情况解决了我的问题... 我必须添加'<br>%Change:{text}'并在括号中指定 text=group_dfff.PERC_CHANGE - 这正是我想要的。然而,text 变量是一个内置的东西,所以我仍然不确定如何添加第四、第五个及更多标签,我希望在悬停数据点时能够看到它们... - DGomonov
4个回答

98

使用Plotly Express时,您需要在创建图形时使用 custom_data 参数。例如:

fig = px.scatter(
    data_frame=df, 
    x='ColX', 
    y='ColY', 
    custom_data=['Col1', 'Col2', 'Col3']
)

然后使用update_traceshovertemplate对其进行修改,将其作为customdata引用。例如:

fig.update_traces(
    hovertemplate="<br>".join([
        "ColX: %{x}",
        "ColY: %{y}",
        "Col1: %{customdata[0]}",
        "Col2: %{customdata[1]}",
        "Col3: %{customdata[2]}",
    ])
)
这需要大量的试错才能弄清楚,因为它没有很好地记录下来,并且custom_datacustomdata之间的不一致性很令人困惑。

这需要大量的尝试和错误来解决,因为它没有很好的记录,而custom_datacustomdata之间的不一致性很令人困惑。


刚才我尝试的时候,不知道为什么custom_data参数会删除所有涉及到的列(在你的情况下是Col1、Col2、Col3),以便在图表上显示。 - Ming Jun Lim
Plotly 真的很酷,只是我希望他们能更认真地设计和记录 API。非常感谢您的分享! - Nils

16

我实际上也遇到过类似的问题,相信我,花了我两个半小时才弄清楚。让我们通过一个例子来理解。

fig = make_subplots(rows=1,cols=2,subplot_titles=('First plot','Second plot'),
                   specs=[[{'type': 'scene'}, {'type': 'scene'}]])

fig.add_trace(go.Scatter3d(x=[0,1,2,3],y=[0,1,2,3],z=[0,1,2,3]), row=1,col=1)
fig.add_trace(go.Scatter3d(x=[0,1,2,3],y=[0,1,2,3], z=[0,1,2,3]), row=1,col=2)

fig.update_layout(title='Add Custom Data')

fig.show()

这将创建两个简单的scatter3d图,其中hoverdata是x、y和z轴。现在您想要将数据m=[9,8,7,6,5]添加到第一个图中。你可以在text参数中解析m并添加hovertemplate

fig.add_trace(go.Scatter3d(x=[0,1,2,3],y=[0,1,2,3],z=[0,1,2,3],
                          text=[9,8,7,6], hovertemplate='<br>x:%{x}<br>y:%{y}<br>z:%{z}<br>m:%{text}'), row=1,col=1)

这应该可以正常工作。但现在我们想在第一张图(或任何图)上添加一个名为n=[5,6,7,8]的列表。这次我们将使用customdata参数。

fig.add_trace(go.Scatter3d(x=[0,1,2,3],y=[0,1,2,3],z=[0,1,2,3],
                          text=[9,8,7,6],customdata=[5,6,7,8],
                          hovertemplate='<br>x:%{x}<br>y:%{y}<br>z:%{z}<br>m:%{text}<br>n:%{customdata}'), row=1,col=1)

现在假设我们要添加第三个自定义数据列表。这就是棘手的部分。您不能解析两个自定义数据列表中的列表,然后调用customdata [0]customdata [1],这并不简单。我们的第三个列表是k=[2,4,6,8]

我们需要像这样的customdata=[[[5],[2]],[[6],[4]],[[7],[6]],[[8],[8]]], 这样它应该可以正常工作。基本上,我们需要给 plotly 一个单独的列表(或数组),其中每个元素都是您想要显示的所有点的列表。

fig.add_trace(go.Scatter3d(x=[0,1,2,3],y=[0,1,2,3],z=[0,1,2,3],
                          text=[9,8,7,6],customdata=[[[5],[2]],
                                                     [[6],[4]],
                                                     [[7],[6]],
                                                     [[8],[8]]],
                          hovertemplate='<br>x:%{x}<br>y:%{y}<br>z:%{z}<br>m:%{text}<br>n:%{customdata[0]}<br>k:%{customdata[1]}'), row=1,col=1)

我们已经快要完成了,但还有一件事情未完成。手动创建像我们在customdata中给出的列表是非常繁琐的工作,因此我们将使用强大的库import numpy as np来自动化它。

n = [5,6,7,8]
k = [2,4,6,8]

nk = np.empty(shape=(4,2,1), dtype='object')
nk[:,0] = np.array(n).reshape(-1,1)
nk[:,1] = np.array(k).reshape(-1,1)
fig.add_trace(go.Scatter3d(x=[0,1,2,3],y=[0,1,2,3],z=[0,1,2,3],
                          text=[9,8,7,6],customdata=nk,
                          hovertemplate='<br>x:%{x}<br>y:%{y}<br>z:%{z}<br>m:%{text}<br>n:%{customdata[0]}<br>k:%{customdata[1]}'), row=1,col=1)

BOOM!如果您想直接从数据框中添加数据,可以将df ['Column name'] 解析为np.array(n)。


9
与上述类似,但我更喜欢一次性完成所有命令,始终使用DataFrame,并坚持使用Plotly而不是Plotly Express:
fig.add_trace(
    go.Scatter(
        x=group_dfff.Months,
        y=group_dfff.Amount,
        customdata=group_dfff.PERC_CHANGE,
        name=i,
        hovertemplate='<br>'.join([
            'Price: $%{y:.2f}',
            'Week: %{x}',
            'Percent Change: %{customdata}',
        ]),
    )
)

还需要注意的是,如果您的DataFrame中有多个“自定义数据”字段(例如“A”和“B”)需要包含在hoverdata中,您可以稍微修改上述代码以包含尽可能多的数据:

fig.add_trace(
    go.Scatter(
        x=group_dfff.Months,
        y=group_dfff.Amount,
        customdata=group_dfff[['A', 'B']],
        name=i,
        hovertemplate='<br>'.join([
            'Price: $%{y:.2f}',
            'Week: %{x}',
            'Field A: %{customdata[0]}',
            'Field B: %{customdata[1]}',
        ]),
    )
)

有没有办法使用适当的字典键而不是一些危险的整数排序方式?js版本在plotly.graph_objects中可以正确地实现这一点,因此应该是可能的。 - mathtick
1
@mathtick 有点类似。JS数组是有序的,但Python字典不是,据我所知,接口层只接受HTML。你需要做一些工作才能实现它,而且对于本质上是静态字符串的东西来说,它最终会变得有点笨重 - 特别是如果你想区分DF列和人性化标签、每个字段在hovertemplate中可能不同的格式等等。如果您预计会经常使用不同的数据框、跟踪、格式选项等来完成此操作...请编写一个自定义函数来构建go.Scatter()实例。 - Sarah Messer
我遇到了类似的问题 - 感谢解决方案!另外,这段代码在悬停时显示所有选定列及其值: hovertemplate="<br>".join([f"{col}: %{{customdata[{idx}]}}" for idx, col in enumerate(selected.columns)]) 其中 selected 是原始 pd.DataFrame 的一个选择。 - michael_s

5

您可以通过以下方式将自定义数据添加到hovertemplate中:

hovertemplate = 'Price: $%{customdata[0]:.2f}'+'<br>Week: %{customdata[1]} ' 
+ '<br>Change: %{customdata[2]}'

customdata 可以是您的 group_dfff,也可以是其他完全不同的数据帧,您可以从中获取要在悬停信息中显示的数据。

这是 plotly 文档上关于添加自定义数据和悬停模板的链接


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接