两个轴都已排序的 Holoviews 热图
Holoviews heatmap with both axes sorted
我有以下代码使用 pandas 和全息视图生成热图:
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)
)
它产生以下内容:
请注意,x 轴 ('source') 的排序不正确。我尝试使用 'sort()' 但它似乎只能对一个轴或另一个轴进行排序。如何使两个轴都针对全息视图热图正确排序?
最佳解决方法 -
到目前为止,我可以通过执行以下操作来绕过它:
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)
)
要实现这种类型的独立排序,您需要手动指定顺序。您可以通过定义维度来预先执行此操作,也可以在创建绘图时重新调整以设置值。
预先定义Dimension
:
# np.unique sorts the unique values by default
source = hv.Dimension("source", values=np.unique(df["source"]))
sink = hv.Dimension("sink", values=np.unique(df["sink"]))
(hv.HeatMap(df, kdims = [source, sink], vdims =['net', 'avg'])
.opts(xticks=None, tools=['hover'], xrotation=90)
)
之后使用redim.values
设置维度值
(hv.HeatMap(data, kdims = ["source", "sink"], vdims =['net', 'avg'])
.opts(xticks=None, tools=['hover'], xrotation=90)
.redim.values(
sink=np.unique(df["sink"]),
source=np.unique(df["source"]))
)
无论哪种情况,您最终都会得到如下所示的情节:
更合适的解决方案是使用@Riddell 的解决方案,但对于重新维度使用:
.redim.values(x=temp['x'].sort_values(), y=temp['y'].sort_values())
为了完成,我强烈建议使用钩子来修改散景的图x_range参数。
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)
def hook(plot, element):
plot.handles['x_range'].factors = sorted(df['source'].unique())
hm = hv.HeatMap(data, kdims = ['source','sink']
, vdims =['net', 'avg']).opts(hooks=[hook])
layout = hv.Layout([hm])
layout.opts(
hv.opts.HeatMap(xticks=None, tools=['hover'], xrotation=90)
)
根据数据的大小,修改散景 x_range 可能比处理 pandas 操作快得多。而且代码更清晰一些,只添加了两行。
缺点是你想使用其他渲染器,如 matplotlib。
我有以下代码使用 pandas 和全息视图生成热图:
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)
)
它产生以下内容:
请注意,x 轴 ('source') 的排序不正确。我尝试使用 'sort()' 但它似乎只能对一个轴或另一个轴进行排序。如何使两个轴都针对全息视图热图正确排序?
最佳解决方法 -
到目前为止,我可以通过执行以下操作来绕过它:
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)
)
要实现这种类型的独立排序,您需要手动指定顺序。您可以通过定义维度来预先执行此操作,也可以在创建绘图时重新调整以设置值。
预先定义Dimension
:
# np.unique sorts the unique values by default
source = hv.Dimension("source", values=np.unique(df["source"]))
sink = hv.Dimension("sink", values=np.unique(df["sink"]))
(hv.HeatMap(df, kdims = [source, sink], vdims =['net', 'avg'])
.opts(xticks=None, tools=['hover'], xrotation=90)
)
之后使用redim.values
设置维度值
(hv.HeatMap(data, kdims = ["source", "sink"], vdims =['net', 'avg'])
.opts(xticks=None, tools=['hover'], xrotation=90)
.redim.values(
sink=np.unique(df["sink"]),
source=np.unique(df["source"]))
)
无论哪种情况,您最终都会得到如下所示的情节:
更合适的解决方案是使用@Riddell 的解决方案,但对于重新维度使用:
.redim.values(x=temp['x'].sort_values(), y=temp['y'].sort_values())
为了完成,我强烈建议使用钩子来修改散景的图x_range参数。
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)
def hook(plot, element):
plot.handles['x_range'].factors = sorted(df['source'].unique())
hm = hv.HeatMap(data, kdims = ['source','sink']
, vdims =['net', 'avg']).opts(hooks=[hook])
layout = hv.Layout([hm])
layout.opts(
hv.opts.HeatMap(xticks=None, tools=['hover'], xrotation=90)
)
根据数据的大小,修改散景 x_range 可能比处理 pandas 操作快得多。而且代码更清晰一些,只添加了两行。
缺点是你想使用其他渲染器,如 matplotlib。