Search code examples
pandasheatmapholoviews

Holoviews heatmap with both axes sorted


I have the following code to produce a heatmap using pandas and holoviews:

cols = ['source','sink','net','avg']
data = [['13002','13002',5.0,2.161478e+06],
['13002','13003',5.0,6.959788e+04],
['13002','23002',5.0,4.233500e+03],
['13002','33006',5.0,8.104000e+03],
['13002','43002',5.0,9.374625e+05],
['13002','43004',5.0,2.865538e+03],
['13002','53001',5.0,1.737890e+05],
['13002','53008',5.0,3.693100e+04],
['13002','53017',5.0,4.541660e+05],
['13002','unk',23.0,1.205498e+05],
['13003','13002',23.0,2.275744e+05],
['13003','43002',23.0,3.250252e+05],
['13003','43003',23.0,4.248433e+04],
['13003','43008',23.0,7.541023e+04],
['13003','53012',23.0,5.000000e+02],
['13003','unk',23.0,5.247462e+03],
['13005','43004',23.0,2.355648e+05],
['23002','13002',23.0,1.317475e+05],
['23002','13003',23.0,1.000000e+04],
['23002','53008',23.0,4.716667e+03]]

df = pd.DataFrame(data, columns=cols)

hm = hv.HeatMap(data, kdims = ['source','sink']
                , vdims =['net', 'avg']).sort(['sink','source'])
layout = hv.Layout([hm])
layout.opts(
    opts.HeatMap(xticks=None, tools=['hover'], xrotation=90)
)

It produces the following:

enter image description here

Note that the x-axis ('source') is not ordered properly. I tried using 'sort()' but it seems to only sort one axis or the other. How can I make both axes be properly sorted for the holoviews heatmap?

BEST WORK AROUND -

So far I can get around it by doing as follows:

df = pd.DataFrame(data, columns=cols)
temp = pd.Series(df.sink.unique(),name='sink').sort_values()
df = df.groupby('source').apply(lambda x: x.merge(temp, how='outer', on='sink'))
df.source = df.source.ffill()
df = df.fillna(0).droplevel([0])

hm = hv.HeatMap(df, kdims = ['source', 'sink']
                , vdims =['net', 'avg']).sort()
layout = hv.Layout([hm])
layout.opts(
    opts.HeatMap(xticks=None, tools=['hover'], xrotation=90)
)

Solution

  • A more appropriate solution is to used the solution by @Riddell but for the re-dimension use:

    .redim.values(x=temp['x'].sort_values(), y=temp['y'].sort_values())