Computing automatically additional plot as a sum of all others

Having 3 line plots in Bokehjs, I would like Bokeh to show a fourth one, which is the sum of the other 3.
Example:

y1=[1,2,3,4,5]
y2=[4,5,6,7,8]
y3=[1,8,2,6,4]

Automatically generated plot would be:

y_all = [6,15,11,17,17]

Is there a way to accomplish this?
Maybe with a js callback?

PS: This is a copy from bokehjs: computing a new plot automatically as sum of all activated plots - Stack Overflow

Absolutely → there are a number of ways to accomplish this. I’m more of a python-base + lots of CustomJS kind of user rather than “pure” BokehJS, so my example will be in python but you should be able to “translate” the logic (and the actual CustomJSTransform code should be practically copy-pastable to BokehJS):

from bokeh.plotting import figure, show
from bokeh.models import ColumnDataSource, Slider, CustomJSTransform
from bokeh.layouts import column
#one datasource since the way you outlined it in your post, I should be able to assume the x values are the same for all lines?
#starting data
data = {'x':[1,2,3,4,5],'y1':[1,2,3,4,5],'y2':[2,1,4,6,4],'y3':[0,4,3,7,1]}
#CDS of this data
src = ColumnDataSource(data)

f = figure()

colors=['red','blue','green']
#plot the "normal" lines with the three colors
for i,y in enumerate(['y1','y2','y3']):
    f.line(x='x',y=y,line_color=colors[i],source=src)
    
#plot the "sum" line driving off a CustomJSTransform
tf = CustomJSTransform(args=dict(src=src)
                       ,v_func='''
                       var new_ysum = [] //array to be populated with the sum
                       const fields= ['y1','y2','y3'] //fields in src you want to sum
                       //iterating through each array index
                       for (var i=0;i<src.data['y1'].length;i++){
                               //calculate a new value that is the sum of all the spec'd fields
                               var new_val = 0
                               for (var ii=0;ii<fields.length;ii++){
                                       new_val = new_val + src.data[fields[ii]][i]                                       
                                       }
                               //push that new value to the new_val array
                               new_ysum.push(new_val)
                               }
                       //have the transform return that result
                       return new_ysum
                       ''')
#then point the "sum" line renderer to run off this transform                     
#only "funny" part is that you still need to specify a field key but this is redundant as the transform does not require it to calculate stuff
#I put 'x' here but it really doesn't matter
f.line(x='x',y={'field':'x','transform':tf},source=src,line_color='black',line_width=3)
show(f)

2 Likes

This topic was automatically closed 90 days after the last reply. New replies are no longer allowed.