Search code examples
pythonpandasbokehholoviewshvplot

hvplot.heatmap with pandas dataframe: How to specify value dimensions?


I have a simple dataframe with columns and rows that I want to visualize using hvpolot.heatmap. I can do something pretty similar with:

df.style.background_gradient(cmap='summer')

.. in Jupyter, looks like: enter image description here

The dataframe is pretty simple:

> df.index
Index(['ackerland', 'friedhof', 'gartenland', 'gehoelz', 'golfplatz',
       'gruenland', 'heide', 'kleingarten', 'laubholz', 'mischholz', 'moor',
       'nadelholz'],
      dtype='object')
> df.columns
Index(['hiking', 'biking', 'walking', 'sport', 'friends', 'family', 'picnic'], dtype='object')

But when I do:

>import hvplot.pandas
>df.hvplot.heatmap(colorbar=True)
ValueError: Dimensions must be defined as a tuple, string, dictionary or Dimension instance, found a NoneType type.```

This does also not work:

>df.hvplot.heatmap(x=df.index, y=df.columns, colorbar=True)
ValueError: The truth value of a Index is ambiguous. Use a.empty, a.bool(), a.item(), a.any() or a.all().

I've read most docs regarding this, but still don't fully understand how to specify value dimensions for pandas dataframe in hvplot/holoviews/bokeh:

[edit] Added feature request


Solution

  • 1) If your data is in the wide format that you have, with categories as index, and columns as values, like this:

    +--------------------------+
    |         colA  colB  colC |
    +--------------------------+
    | group1    10 5.000 1.200 |
    | group2    12 3.000 4.500 |
    | group3    14 1.200 2.300 |
    +--------------------------+
    

    Then you just do df.heatmap.hvplot() with hvplot >= 0.5:

    import pandas as pd
    import holoviews as hv
    import hvplot.pandas
    hv.extension('bokeh')
    
    df = pd.DataFrame({
        'colA': [10, 12, 14],
        'colB': [5, 3.0, 1.2],
        'colC': [1.2, 4.5, 2.3]},
        index=['group1', 'group2', 'group3'],
    )
    
    df.hvplot.heatmap()
    

    If you would like to add data labels to the heatmap you can do:

    heatmap = df.hvplot.heatmap()
    
    heatmap * hv.Labels(heatmap)
    



    2) However when your data is like this where groups are just another column and not the index:

    +------------------------------+
    |      group colA  colB  colC  |
    +------------------------------+
    | 1   group1    10 5.000 1.200 |
    | 2   group2    12 3.000 4.500 |
    | 3   group3    14 1.200 2.300 |
    +------------------------------+
    

    Then you could either set your group as your index with df.set_index('group') (and apply solution 1), or melt your data into a long format:

    df_melt = df.melt(id_vars='group')
    

    After melting your data looks like this:

    +---+--------+----------+--------+
    |   | group  | variable | value  |
    +---+--------+----------+--------+
    | 0 | group1 | colA     | 10.000 |
    | 1 | group2 | colA     | 12.000 |
    | 2 | group3 | colA     | 14.000 |
    | 3 | group1 | colB     | 5.000  |
    | 4 | group2 | colB     | 3.000  |
    +---+--------+----------+--------+
    

    This melted data is in the format where you can use the x and y and C keywords:

    df_melt.hvplot.heatmap(x='group', y='variable', C='value')
    

    Or you can use that melted (long) data to create the heatmap in HoloViews:

    hv.HeatMap(df_melt, kdims=['group', 'variable'], vdims=['value'])
    

    The advantage of melted data is that you can now also easily add data labels to your heatmap:

    heatmap = df_melt.hvplot.heatmap(x='group', y='variable', C='value')
    labels = hv.Labels(data=df_melt, kdims=['group', 'variable'], vdims=['value'])
    
    heatmap * labels
    

    Another (even) easier way to add data labels / values to your heatmap is like this:

    heatmap = df_melt.hvplot.heatmap(x='group', y='variable', C='value')
    heatmap * hv.Labels(heatmap)
    



    Resulting plot:

    nice heatmap with labels using hvplot or holoviews

    More info on heatmaps in hvplot:
    https://hvplot.holoviz.org/reference/pandas/heatmap.html

    More info on heatmaps in holoviews:
    https://holoviews.org/reference/elements/bokeh/HeatMap.html

    More info on (data) labels in holoviews:
    https://holoviews.org/reference/elements/bokeh/Labels.html