Problem with hover display in heatmap with plotlyjs backend

if i use the plotly backend to make a heatmap with a small number of categorical variables then everything is fine

using Plots
plotly()

categories = string.(collect('a':'e'))
n = length(categories) #5
heatmap(categories, categories, rand(n,n))

which is to say that the hover always shows the x and y categories and the value

But when the number of categories becomes large then the x and y axes are, very reasonably, labeled with only a subset of the categories. That’s fine, but the problem is that the hover display doesn’t show the underlying category unless it happens to be displayed along the axis:

categories = string.(collect('a':'z'))
n = length(categories) #26
heatmap(categories, categories, rand(n,n))

gives


or

Finally, my question: Is there a way to force the heatmap function to display the underlying categories even when the categorical values of the x and/or y coords are not displayed along the axis?

You can try this:

using Plots; plotly()
categories = 'a':'z'
n = length(categories) #26
t = (0.5:(n-0.5), categories)
heatmap(categories, categories, rand(n,n), ticks=t)
1 Like

That’s great, thank you.

I’d like to re-open this because I’m confused again. The solution provided for @rafael.guerra works great when the number of categories is relatively small.

But if, for example, I do

using Plots; plotly()
categories = collect(Iterators.flatten(('a':'z', 'A':'Z','0':'9')))
n = length(categories) #62
t = (0.5:(n-0.5), categories)
heatmap(categories, categories, rand(n,n), ticks=t)

then the x and y-axis tick marks become very congested.

But if I ‘thin out’ the tick marks by choosing, for example

indx = 1:10:length(categories)
subset_of_categories = categories[indx]
nsub = length(subset_of_categories)
t = (collect(indx) .- 0.5, subset_of_categories)

then the hover display only shows the category label for points that happen to have an x-value or y-value for which there’s a tickmark. Otherwise you just see a number.

MY QUESTION: Is there a “best of both worlds” choice of settings that leave the tickmarks on the axes as something reasonable (as is automatically the case when we omit the ticks argument to heatmap) but still shows the x and y category labels when I hover over an arbitrary point in the heatmap(as is the case when the tickmarks include all labels)?

Try increasing the plot size by calling heatmap() with the keyword argument size=(1200,1200) or larger.

This was just a minimal example of the issue… In my actual use case I have a date range as the categorical variable on 1 axis and discrete numerical variable on the other axis. So there are hundreds of discrete categorical variables. Which means I can’t make my plot big enough to prevent the tick marks from being congested :smiley:

I like using heatmap in addition to surface because the two visualization tools help me develop intuition and aid pattern recognition in different ways. And if I call

z = [sqrt(x^2 + y^2) for y in 1:n, x in 1:n]
surface(categories, categories, z, ticks=:native)

then all is well, i.e. the x and y axis ticks are subset reasonably AND mouseover shows the categories rather than numbers for the x and y coord of the surface plot.

But ticks=:native doesn’t work with heatmap :< . I don’t know why that would be, since a heatmap is just a visually “flattened” version of a surface plot. But, in any case, I’m simply wondering if there’s a way to get the equivalent of ticks = :native behavior in heatmap

If you’re using dates, try this solution for getting :native working.

No. That doesn’t deal with the problem. But thank you for trying to help. I appreciate the generosity.