Jaffer Wilson
Jaffer Wilson

Reputation: 7273

Python Plotly display other information on Hover

Here is the code that I have tried:

# import pandas as pd
import numpy as np
import plotly.graph_objects as go
from plotly.subplots import make_subplots

df = pd.read_csv("resultant_data.txt", index_col = 0, sep = ",")

display=df[["Velocity", "WinLoss"]]

pos = lambda col : col[col > 0].sum()
neg = lambda col : col[col < 0].sum()

Related_Display_Info = df.groupby("RacerCount").agg(Counts=("Velocity","count"), 
                                                   WinLoss=("WinLoss","sum"),
                                                  Positives=("WinLoss", pos),
                                                   Negatives=("WinLoss", neg),
                                                  )    

# Create figure with secondary y-axis
fig = make_subplots(specs=[[{"secondary_y": True}]])

# Add traces
fig.add_trace(
    go.Scatter(x=display.index, y=display["Velocity"], name="Velocity", mode="markers"),
    secondary_y=False
)

fig.add_trace(
    go.Scatter(x=Related_Display_Info.index, 
               y=Related_Display_Info["WinLoss"],
               name="Win/Loss", 
               mode="markers",
               marker=dict(
                           color=(
                                    (Related_Display_Info["WinLoss"] < 0)
                                 ).astype('int'),
                                colorscale=[[0, 'green'], [1, 'red']]
                           )
               ),
    secondary_y=True,
)

# Add figure title
fig.update_layout(
    title_text="Race Analysis"
)

# Set x-axis title
fig.update_xaxes(title_text="<b>Racer Counts</b>")

# Set y-axes titles
fig.update_yaxes(title_text="<b>Velocity</b>", secondary_y=False)
fig.update_yaxes(title_text="<b>Win/Loss/b>", secondary_y=True)
fig.update_layout(hovermode="x unified")
fig.show()

The output is: images

But I was willing to display the following information when I hover on the point:

RaceCount = From Display dataframe value Number of the race corresponding to the dot I hover on.  
Velocity  = From Display Dataframe value Velocity at that point  
Counts    = From Related_Display_Info Column  
WinLoss   = From Related_Display_Info Column  
Positives = From Related_Display_Info Column  
Negatives = From Related_Display_Info Column

Please can anyone tell me what to do to get this information on my chart?

I have checked this but was not helpful since I got many errors: Python/Plotly: How to customize hover-template on with what information to show?

Data:

RacerCount,Velocity,WinLoss
111,0.36,1
141,0.31,1
156,0.3,1
141,0.23,1
147,0.23,1
156,0.22,1
165,0.2,1
174,0.18,1
177,0.18,1
183,0.18,1
114,0.32,1
117,0.3,1
120,0.29,1
123,0.29,1
126,0.28,1
129,0.27,1
120,0.32,1
144,0.3,1
147,0.3,1
159,0.27,1
165,0.26,1
168,0.25,1
156,0.29,1
165,0.26,1
168,0.26,1
165,0.28,1
213,0.17,1
243,0.15,1
249,0.14,1
228,0.54,1
177,0.67,1
180,0.66,1
183,0.65,1
192,0.66,1
195,0.62,1
198,0.6,1
180,0.66,1
222,0.56,1
114,0.41,1
81,0.82,1
102,0.56,1
111,0.55,1
90,1.02,1
93,1.0,1
90,1.18,1
90,1.18,1
93,1.1,1
96,1.07,1
99,1.04,1
102,0.99,1
105,0.94,1
108,0.92,1
111,0.9,1
162,0.66,1
159,0.63,1
162,0.65,-1
162,0.66,-1
168,0.64,-1
159,0.68,-1
162,0.67,-1
174,0.62,-1
168,0.65,-1
171,0.64,-1
198,0.55,-1
300,0.47,-1
201,0.56,-1
174,0.63,-1
180,0.61,-1
171,0.64,-1
174,0.62,-1
303,0.47,-1
312,0.48,-1
258,0.51,-1
261,0.51,-1
264,0.5,-1
279,0.47,-1
288,0.48,-1
294,0.47,-1
258,0.52,-1
261,0.51,-1
267,0.5,-1
222,0.53,-1
171,0.64,-1
177,0.63,-1
177,0.63,-1

Upvotes: 3

Views: 1222

Answers (1)

Kat
Kat

Reputation: 18714

Essentially, this code ungroups the data frame before plotting to create the hovertemplate you're looking for. As stated in the comments, the data has to have the same number of rows to be shown in the hovertemplate. At the end of my answer, I added the code all in one chunk.

Since you have hovermode as x unified, you probably only want one of these traces to have hover content.

I slightly modified the creation of Related_Display_Info. Instead of WinLoss, which is already in the parent data frame, I modified it to WinLoss_sum, so there wouldn't be a naming conflict when I ungrouped.

Related_Display_Info = df.groupby("RacerCount").agg(
    Counts=("Velocity","count"), WinLoss_sum=("WinLoss","sum"),
    Positives=("WinLoss", pos), Negatives=("WinLoss", neg))

Now it's time to ungroup the data you grouped. I created dui (stands for display info ungrouped).

dui = pd.merge(df, Related_Display_Info, how = "outer", on="RacerCount", 
               suffixes=(False, False))

I created the hovertemplate for both traces. I passed the entire ungrouped data frame to customdata. It looks like the only column that isn't in the template is the original WinLoss.

# create hover template for all traces
ht="<br>".join(["<br>RacerCount: %{customdata[0]}",
                "Velocity: %{customdata[1]:.2f}",
                "Counts: %{customdata[3]}",
                "Winloss: %{customdata[4]}",
                "Positives: %{customdata[5]}",
                "Negatives: %{customdata[6]}<br>"])

The creation of fig is unchanged. However, the traces are both based on dui. Additionally, the index isn't RacerCount, so I used the literal field instead.

# Create figure with secondary y-axis
fig = make_subplots(specs=[[{"secondary_y": True}]])

# Add traces
fig.add_trace(go.Scatter(x=dui["RacerCount"], y=dui["Velocity"], 
                         name="Velocity", mode="markers",
                         customdata=dui, hovertemplate=ht), 
              secondary_y=False)

fig.add_trace(
    go.Scatter(x = dui["RacerCount"], y=dui["WinLoss_sum"], customdata=dui,
               name="Win/Loss", mode="markers", 
               marker=dict(color=((dui["WinLoss_sum"] < 0)).astype('int'),
                           colorscale=[[0, 'green'], [1, 'red']]), 
                           hovertemplate=ht),
    secondary_y=True)

enter image description here

enter image description here

All the code altogether (for easier copy + paste)

import pandas as pd
import numpy as np
import plotly.graph_objects as go
from plotly.subplots import make_subplots

df = pd.read_clipboard(sep = ',')

display=df[["Velocity", "WinLoss"]]

pos = lambda col : col[col > 0].sum()
neg = lambda col : col[col < 0].sum()

Related_Display_Info = df.groupby("RacerCount").agg(
    Counts=("Velocity","count"), WinLoss_sum=("WinLoss","sum"),
    Positives=("WinLoss", pos), Negatives=("WinLoss", neg))

# ungroup the data for the hovertemplate
dui = pd.merge(df, Related_Display_Info, how = "outer", on="RacerCount", 
               suffixes=(False, False))

# create hover template for all traces
ht="<br>".join(["<br>RacerCount: %{customdata[0]}",
                "Velocity: %{customdata[1]:.2f}",
                "Counts: %{customdata[3]}",
                "Winloss: %{customdata[4]}",
                "Positives: %{customdata[5]}",
                "Negatives: %{customdata[6]}<br>"])

# Create figure with secondary y-axis
fig = make_subplots(specs=[[{"secondary_y": True}]])

# Add traces
fig.add_trace(go.Scatter(x=dui["RacerCount"], y=dui["Velocity"], 
                         name="Velocity", mode="markers",
                         customdata=dui, hovertemplate=ht), 
              secondary_y=False)

fig.add_trace(
    go.Scatter(x = dui["RacerCount"], y=dui["WinLoss_sum"], customdata=dui,
               name="Win/Loss", mode="markers", 
               marker=dict(color=((dui["WinLoss_sum"] < 0)).astype('int'),
                           colorscale=[[0, 'green'], [1, 'red']]), 
                           hovertemplate=ht),
    secondary_y=True)

# Add figure title
fig.update_layout(
    title_text="Race Analysis"
)

# Set x-axis title
fig.update_xaxes(title_text="<b>Racer Counts</b>")

# Set y-axes titles
fig.update_yaxes(title_text="<b>Velocity</b>", secondary_y=False)
fig.update_yaxes(title_text="<b>Win/Loss/b>", secondary_y=True)
fig.update_layout(hovermode="x unified")
fig.show()

Upvotes: 4

Related Questions