Seeking general advice on how to implement graph

Hello, I’m new to web development and I’m currently working on a reporting dashboard. Please see attached pdf of what it looks like (I’ve made numerous changes but it still looks more or less the same)

  1. What would be the best way to display the percentages of the graphs? Currently I have a loop that populates it with citations. See code below:

    for i in range (2,24):
    string2 = str(Compl[i])
    string1 = str(Total[i]-Compl[i])
    XLow = 245 * ( round(Compl[i]/Total[i],2))
    XHigh = 30 + 245+245 *( round(Compl[i]/Total[i],2) - 100)

    citation = Label(x=XLow, y= (82+ (37*(i-2))), x_units=‘screen’, y_units=‘screen’,text=string1, render_mode=‘css’,border_line_color=‘black’,text_color = ‘black’, border_line_alpha=0,background_fill_color=‘white’, background_fill_alpha=0)

    p.add_layout(citation)

    citation = Label(x=XHigh, y= (82+ (37*(i-2))), x_units=‘screen’, y_units=‘screen’,text=string2, render_mode=‘css’,border_line_color=‘black’,text_color = ‘black’, border_line_alpha=0,background_fill_color=‘white’, background_fill_alpha=0)

    p.add_layout(citation)

The issue here is that if the number of classes changes, it gets all weird and messed up. It’s not flexible, in other words. What would be the best way to display the corresponding data of each graph? Please note the graphs are percentage-wise but I may need to display the raw numbers, i.e. percent may be 75/25 but number of completed/uncompleted are 3/1, and I need to display 3/1 but have the graph be based on 75/25

  1. Any way to make the graph scale? The website I am developing needs to be accessible by mobile as well. Currently when i change the size of the window, the graph does not respond. Any suggestions?

Thank you so much! Last time someone answered my question with a very helpful response, but when I replied I guess it didn’t save. So thank you again,

Here’s a basic example using randomized data that should help get you started.

I set the height of the figure based on the number of classes, which should help with regard to your scalability requirement.

The labels give the counts of complete and incomplete per your requirement.

The annotations are provided in units of the data to avoid the brittleness where the original code was hardcoded based on screen units, which as you noted would be garbled if the problem size changes. It would also cause problems if you went to more complex layouts with additional models added to your final dashboard.

I didn’t go through the effort of cleaning up all the figure properties and such to match what you might need for aesthetics, but hopefully this provides a useful starting point. Good luck.

#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
"""
import numpy as np

from bokeh.plotting import figure, show
from bokeh.transform import dodge

# Problem dimensions
num_class = 30

# Data
class_names = ['Class {:d}'.format(c) for c in range(num_class)]
class_true = (np.random.rand(num_class)*100).astype(int) # True data, ie "complete"

class_false = (np.random.rand(num_class)*10).astype(int) # False data, i.e. "incomplete"
class_total = class_true + class_false

pct_true = class_true/class_total
pct_false = class_false/class_total

data = dict()
data.update(class_names=class_names)
data.update(class_true=class_true)
data.update(class_false=class_false)
data.update(class_total=class_total)
data.update(pct_true=pct_true)
data.update(pct_false=pct_false)


# Display
px_w = 300
px_h = 30 * num_class # Scale height with number o classes

p = figure(width=px_w, height=px_h,
           x_range=(0.0,1.0), y_range=data['class_names'],
           toolbar_location=None, tools='')

h = p.hbar_stack(['pct_true','pct_false'], y='class_names', source=data,
                 height=0.9, color=('blue','red'), legend_label=['Complete','Incomplete'])

p.text(x=0.45, y=dodge('class_names', 0.0, range=p.y_range),
       text='class_true' , source=data,
       text_align='right', text_baseline='middle', text_color='#FFFFFF', text_font_size={'value': '10pt'})


p.text(x=0.55, y=dodge('class_names', 0.0, range=p.y_range),
       text='class_false' , source=data,
       text_align='left', text_baseline='middle', text_color='#FFFFFF', text_font_size={'value': '10pt'})


show(p)

Regarding your second question, you can try experimenting with the values of the sizing_mode argument. Note that if you use any layout primitives, you have to also specify it for them.