2

I'm having a bit of trouble trying to figure out how to have the legend indicate color for my plotly graph objects heatmap. The legend only needs to communicate the graph colors and what they mean. Essentially all I need is "Purple = Data Not Found" and "Yellow = Data Found". Can anyone help me with this, please?

import plotly.graph_objects as go
import numpy as np
import pandas as pd
from datetime import datetime

df = pd.read_csv('vipr_viri_all_final_df.csv')

truck = '251_QV02_KW_T680_HD_471192'

truck_df = df[df['Truck']==truck]
truck_date_df = truck_df['Date']

dates = list(truck_df['Date'])

vipr_bool = list(truck_df['VIPR Data'])
vipr_bool = [0 if item == False else item for item in vipr_bool]
vipr_bool = [1 if item == True else item for item in vipr_bool]
vipr_first_true = vipr_bool.index(1)
vipr_first_true_reversed = vipr_bool[::-1]
vipr_first_index_reversed = vipr_first_true_reversed.index(1)
vipr_last_true = len(vipr_bool)-1-vipr_first_index_reversed
vipr_low = truck_date_df[vipr_first_true:vipr_first_true+1]
vipr_low = vipr_low.iloc[0]
vipr_high = truck_date_df[vipr_last_true:vipr_last_true+1]
vipr_high = vipr_high.iloc[0]

viri_bool = list(truck_df['Viriciti Data'])
viri_bool = [0 if item == False else item for item in viri_bool]
viri_bool = [1 if item == True else item for item in viri_bool]
viri_first_true = viri_bool.index(1)
viri_first_true_reversed = viri_bool[::-1]
viri_first_index_reversed = viri_first_true_reversed.index(1)
viri_last_true = len(vipr_bool)-1-viri_first_index_reversed
viri_low = truck_date_df[viri_first_true:viri_first_true+1]
viri_low = viri_low.iloc[0]
viri_high = truck_date_df[viri_last_true:viri_last_true+1]
viri_high = viri_high.iloc[0]

if vipr_low < viri_low:
    low_range = vipr_low
else:
    low_range = viri_low

if vipr_high > viri_high:
    high_range = vipr_high
else:
    high_range = viri_high

fig = go.Figure(data=go.Heatmap(
        x=truck_date_df,
        y=['VIPR', 'Viriciti'],
        z=[vipr_bool, viri_bool],
        name=truck,
        colorscale='Viridis',
        showscale=False,
        showlegend=True),
        layout=go.Layout(title=go.layout.Title(text=truck),
                         xaxis_title='Date',
                         yaxis_title='Database',
                         xaxis_range=[low_range, high_range]
    )
)

fig.show()

Graph Output

Output of df.head().to_dict()

{'Unnamed: 0': {0: 0, 1: 1, 2: 2, 3: 3, 4: 4},
 'Truck': {0: '220_2_INTL_PRSTR_ET_619076',
  1: '220_2_INTL_PRSTR_ET_619076',
  2: '220_2_INTL_PRSTR_ET_619076',
  3: '220_2_INTL_PRSTR_ET_619076',
  4: '220_2_INTL_PRSTR_ET_619076'},
 'Date': {0: '2014-01-01',
  1: '2014-01-02',
  2: '2014-01-03',
  3: '2014-01-04',
  4: '2014-01-05'},
 'VIPR Data': {0: False, 1: False, 2: False, 3: False, 4: False},
 'Viriciti Data': {0: False, 1: False, 2: False, 3: False, 4: False}}
2
  • 1
    can you include a small sample of your df by copying the output from df.head().to_dict() into your question? thanks!
    – Derek O
    Commented Oct 10, 2022 at 15:29
  • 1
    @DerekO I have edited my original post to include the sample data you requested.
    – IDK
    Commented Oct 10, 2022 at 17:54

1 Answer 1

1

You can separate your boolean lists [0,0,1,...0] into a list with None as a mask: [None,None,1,...None] and [0,0,None,...0]. Then you can add these as separate heatmap traces so that a legend entry will be generated for each trace.

import plotly.graph_objects as go
import numpy as np
import pandas as pd
from datetime import datetime

# df = pd.read_csv('vipr_viri_all_final_df.csv')

# truck = '251_QV02_KW_T680_HD_471192'
# truck_df = df[df['Truck']==truck]

## recreate data with a similar structure to yours
np.random.seed(42)

truck_df = pd.DataFrame({
    'VIPR Data': np.random.choice([True, False], size=400, p=[0.1,0.9]),
    'Viriciti Data': np.random.choice([True, False], size=400, p=[0.1,0.9]),
    'Date': pd.date_range('2021-01-01',periods=400)
})

truck_date_df = truck_df['Date']

dates = list(truck_df['Date'])

vipr_bool = list(truck_df['VIPR Data'])
vipr_bool = [0 if item == False else item for item in vipr_bool]
vipr_bool = [1 if item == True else item for item in vipr_bool]
vipr_first_true = vipr_bool.index(1)
vipr_first_true_reversed = vipr_bool[::-1]
vipr_first_index_reversed = vipr_first_true_reversed.index(1)
vipr_last_true = len(vipr_bool)-1-vipr_first_index_reversed
vipr_low = truck_date_df[vipr_first_true:vipr_first_true+1]
vipr_low = vipr_low.iloc[0]
vipr_high = truck_date_df[vipr_last_true:vipr_last_true+1]
vipr_high = vipr_high.iloc[0]

viri_bool = list(truck_df['Viriciti Data'])
viri_bool = [0 if item == False else item for item in viri_bool]
viri_bool = [1 if item == True else item for item in viri_bool]
viri_first_true = viri_bool.index(1)
viri_first_true_reversed = viri_bool[::-1]
viri_first_index_reversed = viri_first_true_reversed.index(1)
viri_last_true = len(vipr_bool)-1-viri_first_index_reversed
viri_low = truck_date_df[viri_first_true:viri_first_true+1]
viri_low = viri_low.iloc[0]
viri_high = truck_date_df[viri_last_true:viri_last_true+1]
viri_high = viri_high.iloc[0]

if vipr_low < viri_low:
    low_range = vipr_low
else:
    low_range = viri_low

if vipr_high > viri_high:
    high_range = vipr_high
else:
    high_range = viri_high

fig = go.Figure()

vipr_ones = [None if v==0 else v for v in vipr_bool]
vipr_zeros = [None if v==1 else v for v in vipr_bool]
viri_ones = [None if v==0 else v for v in viri_bool]
viri_zeros = [None if v==1 else v for v in viri_bool]

fig.add_trace(go.Heatmap(
        x=truck_date_df,
        y=['VIPR', 'Viriciti'],
        z=[vipr_zeros, viri_zeros],
        name='Purple = Data Not Found',
        colorscale=[(0.00, "#440154"), (1.0, "#440154")],
        showscale=False,
        showlegend=True,
    )
)

fig.add_trace(go.Heatmap(
        x=truck_date_df,
        y=['VIPR', 'Viriciti'],
        z=[vipr_ones, viri_ones],
        name='Yellow = Data Found',
        colorscale=[(0.00, "#fde725"), (1.0, "#fde725")],
        showscale=False,
        showlegend=True,
    )
)

fig.update_layout(title=go.layout.Title(text='truck'),
                         xaxis_title='Date',
                         yaxis_title='Database',
                         xaxis_range=[low_range, high_range])

fig.show()

enter image description here

3
  • Alternatively, if you don't care about being able to toggle purple or yellow on the heatmap, you could hide the legend corresponding to the heatmap, add some "ghost" markers with the purple and yellow colors (e.g. add a trace with empty data and specify that their colors and purple and yellow so they show up in the legend).
    – Derek O
    Commented Oct 10, 2022 at 16:09
  • Would this code suffice for a ghost-trace? It seems there are no errors when I added it in but the legend is not showing this trace. fig.add_trace(go.Heatmap(x=[0], y=[0], name='Data', colorscale=[(0, '#FDE725')]))
    – IDK
    Commented Oct 10, 2022 at 20:11
  • @Rettro okay i figured it out. you can add the purple and yellow portions of the heatmap separately. then a legend entry will be generated for each trace
    – Derek O
    Commented Oct 10, 2022 at 21:09

Not the answer you're looking for? Browse other questions tagged or ask your own question.