Search code examples
matplotlibbokehholoviews

Holoviews Font Change


Is there a general way to change the font-family, and font size of holoviews plot (rendered by bokeh, and matplotlib, respectively). In particular, I wish to change the font-family and font-size for hv.Bars and hv.Sankey.

The current approach I use to change the font family for the x/y axis labels is to drop into bokeh/matplotlib and change it from there.

import numpy as np
import pandas as pd
import holoviews as hv
from bokeh.plotting import show
from matplotlib import rcParams

categoryA = np.random.choice(['Label1','Label2','Label3','Label4'],size=12)
categoryB = np.random.choice(['Target1','Target2'],size=12)
values = np.random.uniform(0,1,size=12)

dd = pd.DataFrame({'A':categoryA,'B':categoryB,'V':values})

In bokeh, this works okay for Bars


ww = hv.Bars(dd.groupby(['A','B'])['V'].mean().reset_index(),kdims=['A','B'],vdims=['V'])
ww.opts(width=1200)

ww_bokeh = hv.render(ww,backend='bokeh')

ww_bokeh.xaxis.major_label_text_font='arial'
ww_bokeh.xaxis.major_label_text_font_size='16pt'
ww_bokeh.xaxis.axis_label_text_font = 'arial'
ww_bokeh.xaxis.axis_label_text_font_size = '12pt'
ww_bokeh.xaxis.group_text_font='arial'
ww_bokeh = hv.render(ww,backend='bokeh')
show(ww_bokeh)

enter image description here

In matplotlib this doesn't work very well, as I believe the xticks labels are not two different objects.


rcParams['font.family'] = 'sans-serif'
rcParams['font.sans-serif'] = ['Arial']
rcParams['xtick.labelsize'] = '16'
mm = hv.Bars(dd.groupby(['A','B'])['V'].mean().reset_index(),kdims=['A','B'],vdims=['V'])
mm.opts(aspect=5,fig_size=600)

enter image description here

For Sankey, I have no idea how to change the label font size and family.

from holoviews import opts
hv.extension('bokeh')

tt = hv.Sankey(dd)
tt.opts(opts.Sankey(edge_color=dim('A').str(),label_position='outer'))
tt.opts(opts.Label(text_font_size='20pt')) #this does nothing, as I dont think the labels are Label objects
tt.opts(opts.Text(fontscale=3)) #this also does nothing, as I dont think the labels are Text objects either
tt.opts(height=600,width=800)

enter image description here

The font-family is important to change in my case, as well as the label size in the Sankey plot. For reference I am using: bokeh version 1.4.0, matplotlib version 3.1.3, holoviews version 1.13.0a22.post4+g26aeb5739, and python version 3.7 in a jupyter notebook.

I have tried to delve into the source code, but got lost. So any advice or direction would be appreciated.


Solution

  • You should use hook http://holoviews.org/user_guide/Customizing_Plots.html#Plot-hooks

    def hook(plot, element):
        plot.handles['text_1_glyph'].text_font = 'arial'
        plot.handles['text_1_glyph'].text_font_size = '16pt'
        plot.handles['text_2_glyph'].text_font = 'arial'
        plot.handles['text_2_glyph'].text_font_size = '16pt'
    tt = hv.Sankey(dd)
    tt.opts(opts.Sankey(edge_color=hv.dim('A').str(),label_position='outer'))
    tt.opts(height=600,width=800)
    tt.opts(hooks=[hook])
    

    sankey