Plotly: How to round display text in annotated heatmap but keep full format on hover?
Asked Answered
L

5

9

I am drawing a correlation matrix of the Titanic dataset.

df_corr = df.corr()

Originally, the matrix looks like this:

fig = ff.create_annotated_heatmap(
            z=df_corr.to_numpy(),
            x=df_corr.columns.tolist(),
            y=df_corr.index.tolist(),
            zmax=1, zmin=-1,
            showscale=True,
            hoverongaps=True
            )
# add title
fig.update_layout(title_text='<i><b>Correlation not round</b></i>')

not_round

I want to round the float number, so they display less digits after the . dot.

The current workaround is actually round the pandas dataframe before input.

df_corr_round = df_corr.round(3)
fig = ff.create_annotated_heatmap(
            z=df_corr_round.to_numpy(),
            x=df_corr.columns.tolist(),
            y=df_corr.index.tolist(),
            zmax=1, zmin=-1,
            showscale=True,
            hoverongaps=True
            )
# add title
fig.update_layout(title_text='<i><b>Correlation round</b></i>')

round

But the workaround also rounds the text when I hover mouse over. I want hover text in full detail while display text are round.

Can I display less digits on each cell without changing the input dataframe ?

Limp answered 25/1, 2021 at 8:48 Comment(0)
D
7

I can only assume that you're building your ff.create_annotated_heatmap() from a list of lists as they do in the docs under Annotated Heatmaps in Python. And don't worry if you're using a pandas dataframe instead. The complete snippet below will show you how you construct a correlation matrix from a pandas dataframe with multiple timeseries of stocks px.data.stocks, and then make a list of lists using df.values.tolist() to build an annotated heatmap. If you're doing something similar, then one way of building the annotations would be to define a text like this:

z_text = [[str(y) for y in x] for x in z]

And then all you'll need to get the number of digits you want is use round():

z_text = [[str(round(y, 1)) for y in x] for x in z]

As you can see below, this approach (1) does not alter the source dataframe like df_corr.round() would have, (2) shows only 1 digit in the figure, and (3) shows a longer number format on hover. In the image I'm hovering on MSFT / FB = 0.5

enter image description here

Complete code:

import plotly.express as px
import plotly.figure_factory as ff
import pandas as pd

df = px.data.stocks()#.tail(50)
df = df.drop(['date'], axis = 1)
dfc = df.corr()
z = dfc.values.tolist()

# change each element of z to type string for annotations
# z_text = [[str(y) for y in x] for x in z]
z_text = [[str(round(y, 1)) for y in x] for x in z]

# set up figure 
fig = ff.create_annotated_heatmap(z, x=list(df.columns),
                                     y=list(df.columns),
                                     annotation_text=z_text, colorscale='agsunset')

# add title
fig.update_layout(title_text='<i><b>Confusion matrix</b></i>',
                  #xaxis = dict(title='x'),
                  #yaxis = dict(title='x')
                 )

# add custom xaxis title
fig.add_annotation(dict(font=dict(color="black",size=14),
                        x=0.5,
                        y=-0.15,
                        showarrow=False,
                        text="",
                        xref="paper",
                        yref="paper"))

# add custom yaxis title
fig.add_annotation(dict(font=dict(color="black",size=14),
                        x=-0.35,
                        y=0.5,
                        showarrow=False,
                        text="",
                        textangle=-90,
                        xref="paper",
                        yref="paper"))

# adjust margins to make room for yaxis title
fig.update_layout(margin=dict(t=50, l=200))

# add colorbar
fig['data'][0]['showscale'] = True
fig.show()
Debarath answered 25/1, 2021 at 10:9 Comment(0)
J
1

I don't have the data at hand, so I haven't been able to check the execution, but I think the following code will work. Please refer to the official reference.

df_corr_round = df_corr.round(3)
fig = ff.create_annotated_heatmap(
            z=df_corr,
            x=df_corr.columns.tolist(),
            y=df_corr.index.tolist(),
            zmax=1, zmin=-1,
            showscale=True,
            hoverongaps=True,
            annotation_text=df_corr_round.to_numpy(),
            )
# add title
fig.update_layout(title_text='<i><b>Correlation round</b></i>')
Jumpy answered 25/1, 2021 at 9:16 Comment(0)
A
1

Set texttemplate and hovertemplate using update_traces. Also need to declare text_auto=True

fig = px.imshow(
    matrix,  
    text_auto=True, 
    aspect="auto", 
    color_continuous_scale='Viridis'
)

fig.update_traces(
    texttemplate='%{z:.2f}',
    hovertemplate=("%{x}<br>%{y}<br><b>correlation: %{z}</b><extra></extra>")
)
Arri answered 20/6, 2023 at 2:33 Comment(0)
S
0

You should add the ".round()" method. You can do the same manipulations with dataframes.

The following code is for values with non-rounded matrix values with the plotly.express:

import plotly.express as px
import numpy as np

fig = px.imshow(
    np.random.rand(4, 4),
    text_auto=True
)
fig.show()

The graph with non-rounded values

And now with rounded:

import plotly.express as px
import numpy as np

fig = px.imshow(
    np.random.rand(4, 4).round(2),
    text_auto=True
)
fig.show()

With rounded values

Synapsis answered 1/5, 2023 at 7:7 Comment(0)
L
0

Use text_auto='.2f' parameter to round to two decimal places.

See: https://plotly.com/python-api-reference/generated/plotly.express.imshow

Liebowitz answered 1/4 at 21:44 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.