✊🏿 Black Lives Matter. Please consider donating to Black Girls Code today.
⚡️ Concerned about the grid? Kyle Baranko teaches how to predicting peak loads using XGBoost. Register for the August webinar!

Plotly/Dash Heatmap customdata

I’m using Dash, and I made a heatmap (go.Heatmap). It works, it’s visible, it’s gorgeous.

Now I’m trying to add customdata to it (to be used on a click event later, aka I’m accessing clickdata later). I have two bar graphs were I put in customdata and when I click on them, I get the customdata field in my clickdata. I have tried and failed to do the same with the heatmap. Here is a dummy example of what I’m writing:

trace_heatmap = go.Heatmap(
x=xlabels,
y=ylabels,
z=zdata,
customdata=my_list_that_works_correctly_for_text,
colorscale=colorscale,
text=my_list_that_works_correctly_for_text,
hoverinfo=‘text+x+y’)

Everything works, except the customdata. In this example, I’ve set it equal to the same thing as what I’m using for the text field, as both are lists and the text one worked, so I thought it’d be a good thing to test with. But, as said above, when I click a point and access the clickdata, there is no customdata at all. Any guidance would be appreciated!

2 Likes

Thanks for reporting @raaid!

I have replicated the issue with this example:

import dash
from dash.dependencies import Input, Output
import dash_html_components as html
import dash_core_components as dcc

import json

app = dash.Dash()
app.layout = html.Div([
    dcc.Graph(
        id='heatmap',
        figure={
            'data': [{
                'z': [
                    [1, 2, 3],
                    [4, 5, 6]
                ],
                'text': [
                    ['a', 'b', 'c'],
                    ['d', 'e', 'f']
                ],
                'customdata': [
                    ['c-a', 'c-b', 'c-c'],
                    ['c-d', 'c-e', 'c-f'],
                ],
                'type': 'heatmap'
            }]
        }
    ),
    html.Div(id='output')
])


@app.callback(
    Output('output', 'children'),
    [Input('heatmap', 'hoverData'),
     Input('heatmap', 'clickData')])
def display_hoverdata(hoverData, clickData):
    return [
        json.dumps(hoverData, indent=2),
        html.Br(),
        json.dumps(clickData, indent=2)
    ]


if __name__ == '__main__':
    app.run_server(debug=True)

Looks like a bug to me, I’ll have to look into this a little bit deeper.

Thanks for responding and looking into it! =)

Any updates in looking into this, @chriddyp ?

No updates on this yet

It looks like this is possible in plotly.js: https://codepen.io/chriddyp/pen/NagXpM?editors=1011, so this is probably a bug in the Graph component itself

Hi @chriddyp I am also experiencing this issue in Scatter traces using mode=‘lines’. The bug does indeed seem to be in the Graph component, although my JS knowledge is very limited, I am identifying the conditional below as the likely culprit:

            if (has('curveNumber', fullPoint) &&
                has('pointNumber', fullPoint) &&
                has('customdata', data[pointData.curveNumber])
            ) {
                pointData['customdata'] = data[
                    pointData.curveNumber
                ].customdata[fullPoint.pointNumber];
            }

The bug seems to be that elements (such as lines) which do not have pointNumber attributes are then being cut off from having customdata.

Any chance this bug will be addressed in the near future?

Btw, first plotly comment of mine and just want to say thanks for the amazing work Chris!

Hm, odd. I thought that mode: 'lines' would still have pointNumber. Can you make a small, reproducable example?

Also, welcome to dash! :slightly_smiling_face:

1 Like

A post was split to a new topic: dcc.Graph - only curveNumber is showing up

This still appears to be a problem today (dash==1.13.4, plotly==4.8.1). customdata from go.Heatmap can appear in the figure’s hovertemplate but not in clickdata.

My current solution is to include the necessary data in the figure’s text attribute and parse it out from clickdata['points'][0]['text'] but this is less than ideal.

1 Like