Search code examples
pythongraphplotlyhoverheatmap

How do I add more data to the hover of a density heatmap in Plotly?


I have a density heatmap using the Plotly library, specifically Plotly Express for Python. In it, the x-axis corresponds to the 'Father's Education' column from the 'total' dataframe, the y-axis corresponds to the 'Mother's Education' column, and the z-axis corresponds to the 'Percentage' column. What I want is to additionally include the 'Frequency' column in the hover information, so that this data is also displayed when hovering over a cell. I've tried using the 'text' parameter, but it's not available for the density heatmap. As a result, I'm currently experimenting with the 'meta' parameter, but it's displaying '%{data[n[.meta[i]}' instead of the frequency.

fig_heatmap = px.density_heatmap(total,
                                 x='Estudios de la madre',
                                 y='Estudios del padre',
                                 z='Porcentaje',
                                 category_orders={'Estudios de la madre': orden_estudios,
                                                      'Estudios del padre': orden_estudios},
                                 text_auto=True,
                                 color_continuous_scale='blues',
                                 range_color=[0, 15])
fig_heatmap.update_coloraxes(colorbar_title='Porcentaje')
fig_heatmap.update_traces(meta=total.Frecuencia,
                          hovertemplate='Estudios de la madre: %{x}<br>' +
                                       'Estudios del padre: %{y}<br>' +
                                       'Porcentaje: %{z}<br>' +
                                       'Frecuencia: %{data[n[.meta[i]}')
                             

st.plotly_chart(fig_heatmap, use_container_width=True)

Here are some sample data:

data = [
    ("Primaria o secundaria", "Primaria o secundaria", 320, 41.03),
    ("Primaria o secundaria", "Bachillerato", 120, 15.42),
    ("Bachillerato", "Bachillerato", 150, 19.27),
    ("Bachillerato", "Primaria o secundaria", 80, 10.27),
    ("Primaria o secundaria", "Carrera técnica", 50, 6.42),
    ("Primaria o secundaria", "No sé", 40, 5.14),
    ("Carrera técnica", "Carrera técnica", 30, 3.85),
    ("Carrera técnica", "Primaria o secundaria", 20, 2.57),
    ("No sé", "No sé", 20, 2.57),
    ("Bachillerato", "Carrera técnica", 10, 1.28),
    ("Licenciatura", "Primaria o secundaria", 10, 1.28),
    ("Carrera técnica", "Bachillerato", 5, 0.64),
    ("Primaria o secundaria", "Licenciatura", 5, 0.64),
    ("Bachillerato", "Licenciatura", 5, 0.64),
    ("Bachillerato", "No sé", 5, 0.64),
    ("Licenciatura", "Bachillerato", 5, 0.64),
    ("Licenciatura", "Licenciatura", 5, 0.64),
    ("No sé", "Primaria o secundaria", 5, 0.64),
    ("Licenciatura", "No sé", 5, 0.64),
    ("Carrera técnica", "Licenciatura", 5, 0.64),
    ("Licenciatura", "Carrera técnica", 5, 0.64),
    ("Carrera técnica", "No sé", 5, 0.64),
    ("No sé", "Bachillerato", 5, 0.64),
    ("No sé", "Carrera técnica", 5, 0.64),
    ("Posgrado", "Primaria o secundaria", 5, 0.64),
    ("Carrera técnica", "Posgrado", 5, 0.64),
    ("Posgrado", "Carrera técnica", 5, 0.64),
    ("Posgrado", "Bachillerato", 5, 0.64),
    ("Posgrado", "Posgrado", 5, 0.64),
    ("No sé", "Licenciatura", 5, 0.64),
    ("Bachillerato", "Posgrado", 5, 0.64),
    ("Posgrado", "Licenciatura", 5, 0.64),
    ("Licenciatura", "Posgrado", 5, 0.64),
    ("Posgrado", "No sé", 5, 0.64),
    ("Primaria o secundaria", "Posgrado", 5, 0.64)
]

Solution

  • If custom data is to be added to the hover template, it must be equal to the data structure of the graph. In this case, it is a heatmap, so multiple arrays of rows and columns are required. I am converting the data from submitted data to a horizontal format to match the data structure of the graph and sorting each of the category columns. The entirety of that data frame is given to the custom data as an array.

    import pandas as pd
    total = pd.DataFrame(data)
    total.columns = ['Estudios de la madre','Estudios del padre','Frecuencia','Porcentaje']
    
    df = total.pivot(index='Estudios del padre', columns='Estudios de la madre', values='Frecuencia')
    col_order = ['Primaria o secundaria','Bachillerato','Carrera técnica','No sé','Licenciatura','Posgrado']
    df = df.reindex(columns=col_order)
    df = df.reindex(index=col_order) 
    
    import plotly.express as px
    
    fig_heatmap = px.density_heatmap(total,
                                     x='Estudios de la madre',
                                     y='Estudios del padre',
                                     z='Porcentaje',
                                     # category_orders={'Estudios de la madre': orden_estudios,
                                     #                      'Estudios del padre': orden_estudios},
                                     text_auto=True,
                                     color_continuous_scale='blues',
                                     range_color=[0, 15])
    fig_heatmap.update_coloraxes(colorbar_title='Porcentaje')
    fig_heatmap.update_traces(meta=df.values,
                              hovertemplate='Estudios de la madre: %{x}<br>' +
                                           'Estudios del padre: %{y}<br>' +
                                           'Porcentaje: %{z}<br>' +
                                           'Frecuencia: %{meta}')
                                 
    fig_heatmap.show()
    #st.plotly_chart(fig_heatmap, use_container_width=True)
    

    enter image description here