How to add a property to DF, group by that property, and add traces by group

I have a dataframe that describes a series of random lines. Each line is subdivided into a number of intervals.

Each interval has a grade value that gets assigned a color.

Here is drawn the lines on the (3D Spatial) chart:

def draw_shaft_line(coord):
fig.add_trace(go.Scatter3d(
x = coord[‘line_trace’][‘x’],
y = coord[‘line_trace’][‘y’],
z = coord[‘line_trace’][‘z’],
mode=‘lines’,
line = dict(
color=’#AAA’,
width=3,
),
hovertext=coord[‘shaft_line_id’],
hoverinfo=‘text’,
showlegend=False
))
self.shaft_lines_df.apply(draw_shaft_line, axis=1)

And then we draw the colored intervals onto each line (several intervals per line, as many as 20):

def draw_shaft_line_interval(row):
fig.add_trace(go.Scatter3d(
x = row[‘line_interval’][‘x’],
y = row[‘line_interval’][‘y’],
z = row[‘line_interval’][‘z’],
mode=‘lines’,
line=dict(
color=self.interval_color_lookup(row[‘grade’]),
width=15,
),
hovertext=f"{row[‘id_number’]} {row[‘grade’]} deg.",
hoverinfo=‘text’,
showlegend=True
))
intervals_df.apply(draw_shaft_interval, axis=1)

The function “interval_color_lookup()” returns one of 15 specific colors, depending on which grade range the interval falls into (e.g. grade between 1.5 and 2 returns rgb(128,64,0), between 2 and 2.5 something else).

THE PROBLEM IS that we need to display a Plotly legend that maps the colors to their grades. However, because I am drawing one trace for each interval, the legend is meaningless (displays multiple instances of each mapping, one for each interval when it should be one for each color).

One idea was to group the intervals by color, and then loop over those intervals to draw the traces. I have not been successful making that work. I tried numerous variations on this code:

def draw_shaft_line_interval(row):
fig.add_trace(go.Scatter3d(
x = row[‘line_interval’][‘x’],
y = row[‘line_interval’][‘y’],
z = row[‘line_interval’][‘z’],
mode=‘lines’,
line=dict(
color=self.interval_color_lookup(row[‘grade’]),
width=15,
),
hovertext=f"{row[‘id_number’]} {row[‘grade’]} deg.",
hoverinfo=‘text’,
showlegend=True
))

row should be a row of the df, but it is the id_number (the index?)

def apply_colors(row):
return self.interval_color_lookup(row[‘grade’], axis=1)
intervals_df[‘color’] = intervals_df.apply(apply_colors)
intervals_df_grouped = intervals_df.groupby(‘color’)
intervals_df_grouped.apply(draw_shaft_line_interval, axis=1)

Can anyone help fix this broken code, or show a better way to do this?

Many thanks

Hi,

I think that you are looking for grouped legend items:

It should be straightforward to use it in your case, but please let us know if it an issue. Hope this helps!