Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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:

  • Bokeh Heatmap Doc
  • Pandas Dataframe Plot Doc
  • hvplot plot doc
  • hvplot intro with pd.df
  • oloviews heatmap doc

[edit] Added feature request

like image 483
Alex Avatar asked Mar 05 '23 07:03

Alex


2 Answers

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

like image 132
Sander van den Oord Avatar answered Apr 30 '23 23:04

Sander van den Oord


For what you want, you can do :

df.hvplot.heatmap(x='index', y='columns', colorbar=True)
like image 42
lejedi76 Avatar answered May 01 '23 00:05

lejedi76