Search code examples
pythonplotlyscatter

Plotly - "grouped" scatter plot


Suppose I have the following pandas data frame:

import pandas as pd
d = {'Person': ['Bob']*9 + ['Alice']*9,
    'Time': ['Morining']*3 + ['Noon']*3 + ['Evening']*3 + ['Morining']*3 + ['Noon']*3 + ['Evening']*3,
    'Color': ['Red','Blue','Green']*6,
    'Energy': [1,5,4,7,3,6,8,4,2,9,8,5,2,6,7,3,8,1]}
df = pd.DataFrame(d)

enter image description here

How can I create a plot like this? enter image description here (Excuse the crude plotting)

I've tried tricking scatter, strip and box plots into this, but with no success.

Thank you!


Solution

    • generate a scatter trace per Person
    • a bit of logic on x so that each person is offset. Hence hovertext and xaxis ticks
    import plotly.graph_objects as go
    
    xbase = pd.Series(df["Time"].unique()).reset_index().rename(columns={"index":"x",0:"Time"})
    dfp = df.merge(xbase, on="Time").set_index("Person")
    
    go.Figure(
        [
            go.Scatter(
                name=p,
                x=dfp.loc[p, "x"] + i/10,
                y=dfp.loc[p, "Energy"],
                text=dfp.loc[p, "Time"],
                mode="markers",
                marker={"color": dfp.loc[p, "Color"], "symbol":i, "size":10},
                hovertemplate="(%{text},%{y})"
            )
            for i, p in enumerate(dfp.index.get_level_values("Person").unique())
        ]
    ).update_layout(xaxis={"tickmode":"array", "tickvals":xbase["x"], "ticktext":xbase["Time"]})
    

    enter image description here