I recently ran into the issue of changing how many ticks I want displayed on the x-axis in a holoviews plot. My data ranged from 0 to 100, but it was categorical in the pandas dataframe. Simple solutions don’t work in this case as categorical data can’t have the ticks changed easily in opts. Instead, I found this solution at: https://stackoverflow.com/questions/49460699/bokeh-plot-custom-categorical-tick-labels
Implementing it in my case allowed me to go from:
To this:
Code for the solution is below. Mainly, making the CategoricalAxis not visible and adding in a LinearAxis with FixedTicker did the trick.
import holoviews as hv from bokeh.models import CategoricalTicker, FixedTicker, Ticker from bokeh.models.formatters import NumeralTickFormatter from bokeh.util.compiler import TypeScript from bokeh.plotting import show from bokeh.io import output_notebook, export_png from bokeh.models.axes import LinearAxis from bokeh.layouts import gridplot def format_x_axis(p): # Remove default axis p.xaxis.visible = False # Add custom axis ticker = FixedTicker(ticks=[0,50,100]) xaxis = LinearAxis(ticker=ticker) xaxis.axis_label = "Objective" p.add_layout(xaxis, 'below') return p # Create a box plot to show how turning performs def create_boxwhisker_custom_ticks(df, group_col, y_col, title, ylim=(-1.2,0)): boxwhisker = hv.BoxWhisker(df, [group_col], y_col).opts(width=300,xrotation = 90,ylim=ylim, title=title) return boxwhisker plots = [] plot_width = 400 plot_height= 200 for t in wt_treatments: t += "_wt" filtered_df = wt_best_last_gen_per_rep_full_results_df[wt_best_last_gen_per_rep_full_results_df.Trt == t] filtered_df = filtered_df[filtered_df.Task == "wall"] wall = create_boxwhisker_custom_ticks(filtered_df, 'Subtask', 'Fitness', f'{wt_treatment_mapping[t]} Wall Crossing').opts(width=plot_width, height=plot_height) wall = format_x_axis(hv.render(wall)) filtered_df = wt_best_last_gen_per_rep_full_results_df[wt_best_last_gen_per_rep_full_results_df.Trt == t] filtered_df = filtered_df[filtered_df.Task == "turn"] turn = create_boxwhisker_custom_ticks(filtered_df, 'Subtask', 'Fitness', f'{wt_treatment_mapping[t]} Turning').opts(width=plot_width, height=plot_height) turn = format_x_axis(hv.render(turn)) plots.append([wall,turn]) # make a grid grid = gridplot(plots) show(grid)