0

Trying to add data to hover of boxplot express in plotly and following the instructions here in plotly 5.4.1. It is mentioned in the tutorial that additional information to be shown in the hover can be added by hover_data and hover_name argument. However, The additional hover data, in this case information from continent column, is not presented in the hover. I am not sure what is going wrong here? (Here is the code I test in Google colab)

import plotly.express as px
import pandas as pd
import numpy as np
np.random.seed(1234)

df = pd.DataFrame(np.random.randn(20, 1),columns=['Col1'])
df['country']=['canada','france']*10
df['continent']=['america','europe']*10

fig = px.box(df, x="country", y="Col1",  hover_data=['continent'])

fig.show()

Here is what i get in google colab:

plotly boxplot in google colab

Error I get with suggested solution (this was solved with pip install plotly --upgrade): enter image description here

The solution offered by @Rob works but to make it a generic function, here is what I wrote out of it:

def box_with_hover(df,x,y,hover_data):    
  fig = px.box(df, x=x, y=y, hover_data=[hover_data])

  fig.add_traces(
      px.bar(
          df.groupby([x, hover_data], as_index=False).agg(
              base=(y, "min"), y=(y, lambda s: s.max() - s.min())
          ),
          x=x,
          base="base",
          y="y",
          hover_data={hover_data:True, x:True, "base":False, "y":False},
      )
      .update_traces(opacity=0.1)
      .data   ).update_layout(bargap=0.8)


  fig.show()
Masih
  • 15
  • 5
  • I'm not sure what the problem is. When you hover your mouse over the boxes, it will show the data. – morhc Nov 25 '21 at 16:52
  • @morhc, continent data is shown?! are you testing it on google colab? could you share screen shot please? thanks – Masih Nov 25 '21 at 17:24
  • It's the same result that you have in your screenshot. Is this not the data that you want -- if so please clarify the question. – morhc Nov 25 '21 at 17:31

1 Answers1

0
  • this is similar to Change Plotly Boxplot Hover Data
  • boxplot hover info is within javascript layer of plotly. Hence have overlayed a bar plot where hover can be controlled in way you require. When you hover over boxplot you get standard boxplot hover. bar different hover info
import plotly.express as px
import pandas as pd
import numpy as np

np.random.seed(1234)

df = pd.DataFrame(np.random.randn(20, 1), columns=["Col1"])
df["country"] = ["canada", "france"] * 10
df["continent"] = ["america", "europe"] * 10

fig = px.box(df, x="country", y="Col1", hover_data=["continent"])

fig.add_traces(
    px.bar(
        df.groupby(["country", "continent"], as_index=False).agg(
            base=("Col1", "min"), y=("Col1", lambda s: s.max() - s.min())
        ),
        x="country",
        base="base",
        y="y",
        hover_data={"continent":True, "country":True, "base":False, "y":False},
    )
    .update_traces(opacity=0.1)
    .data
).update_layout(bargap=0.8)


fig

enter image description here

generic function

import plotly.express as px
import pandas as pd
import numpy as np

np.random.seed(1234)

df = pd.DataFrame(np.random.randn(20, 1), columns=["Col1"])
df["country"] = ["canada", "france"] * 10
df["continent"] = ["america", "europe"] * 10
df["letter"] = list("AB") * 10


def box_with_hover(*args, **kwargs):
    if isinstance(args[0], pd.DataFrame):
        kwargs["data_frame"] = args[0]
    fig = px.box(**kwargs)

    fig.add_traces(
        px.bar(
            kwargs["data_frame"]
            .groupby([kwargs["x"]], as_index=False)
            .agg(
                **{
                    **{
                        "base": (kwargs["y"], "min"),
                        "y": (kwargs["y"], lambda s: s.max() - s.min()),
                    },
                    **{c: (c, "first") for c in kwargs["hover_data"]},
                }
            ),
            x=kwargs["x"],
            base="base",
            y="y",
            hover_data={
                **{c: True for c in kwargs["hover_data"]},
                **{kwargs["x"]: True, "base": False, "y": False},
            },
        )
        .update_traces(opacity=0.1)
        .data
    ).update_layout(bargap=0.8)
    return fig


box_with_hover(
    df.reset_index(), x="country", y="Col1", hover_data=["continent", "letter", "index"]
)
Rob Raymond
  • 29,118
  • 3
  • 14
  • 30
  • Thanks @rob. I get this error with this solution bar() got an unexpected keyword argument 'base' – Masih Nov 26 '21 at 15:51
  • I'm using plotly 5.4.0, pandas 1.3.4. are you getting that error with exactly code I put in answer? `df.groupby(["country", "continent"], as_index=False).agg( base=("Col1", "min"), y=("Col1", lambda s: s.max() - s.min()) )` does this work? I'm suspecting a pandas version issue with named aggregations – Rob Raymond Nov 26 '21 at 16:04
  • I updated plotly and pandas version in google colab with : pip install plotly==5.4.0 and pip install pandas==1.3.4. I added the plot of error in the question. – Masih Nov 26 '21 at 16:13
  • would it be possible for you to check this in google colab? – Masih Nov 26 '21 at 16:16
  • it works in Colab, just need to run `pip install plotly --upgrade` first and restart runtime – Rob Raymond Nov 26 '21 at 17:40
  • Yes, the upgrade solves the problem. This is a bit complicated way. Can we write a function out of this? I can give it a try but was wondering is there any reason there is no function for it out there yet? Thanks @Rob – Masih Nov 29 '21 at 16:03
  • I've attempted to code up as a generic function. just coding, but I definitely have not managed all edge cases – Rob Raymond Nov 29 '21 at 17:49