bokeh 2nd: layouts

Why layout for different or similar charts is so attracting?

Bokeh Plot

bokeh2

layouts

  • arranging multiple plots
    • arranging plots & controls visually on a page
      • rows, columns
      • grid arrangements
      • tabbed layouts
In [1]:
from bokeh.layouts import row, column
  • pass plots to row() or column()
  • rows or columns can be nested
In [2]:
from bokeh.sampledata.iris import flowers
from bokeh.plotting import figure
from bokeh.io import output_file, output_notebook, show
from bokeh.models import ColumnDataSource
In [3]:
output_notebook()
Loading BokehJS ...
In [4]:
data=ColumnDataSource(flowers)
flowers.head(1)
Out[4]:
sepal_length sepal_width petal_length petal_width species
0 5.1 3.5 1.4 0.2 setosa
In [5]:
p1=figure(plot_width=200, plot_height=200, title='sepal_L vs. petal_L')
p2=figure(plot_width=200, plot_height=200, title='sepal_W vs. petal_W')
p3=figure(plot_width=200, plot_height=200, title='sepal_L vs. sepal_W')
p4=figure(plot_width=200, plot_height=200, title='petal_L vs. petal_W')
In [6]:
p1.circle(x='sepal_length',y='petal_length',source=data,alpha=0.6)
p2.square(x='sepal_width',y='petal_width',source=data,color='red',alpha=0.6)
p3.x(x='sepal_length',y='petal_length',source=data,color='green',alpha=0.6)
p4.diamond(x='petal_length',y='petal_width',source=data,color='purple',alpha=0.6)
Out[6]:
<bokeh.models.renderers.GlyphRenderer at 0x7fd77e389f10>
In [7]:
lay=row(p1,p2,p3,p4)
show(lay)
In [8]:
lay=column(row(p1,p2),row(p3,p4))
show(lay)
In [9]:
lay=row(column(p1),row(p2,p3,p4))
show(lay)
  • sizing_mode='scale_width'
    • fit width by how many plots
In [10]:
lay=row([p3,p4,p2],sizing_mode='scale_width')
show(lay)

advanced layouts

  • Gridplots
    • pass plots to gridplot()
      • list of lists
        • each inner list represents a row
        • each inner list should be the same length
        • None as placeholder
In [11]:
from bokeh.layouts import gridplot
In [12]:
lay=gridplot([None, p1],[p2, p3],[p4, None])

show(lay)

Tabbed Layouts

  • from bokeh.models.widgets import Tabs, Panel
In [13]:
from bokeh.models.widgets import Tabs, Panel
In [14]:
# Create a Panel with a title for each tab
first = Panel(child=row(p1,column(p2,p3)), title='first')
second = Panel(child=p4,title='second')
In [15]:
# Put the Panels in a Tabs object
tabs = Tabs(tabs=[first, second])
# output_file('test.html')

show(tabs)

! Linking plots together

Linking axes

In [16]:
p1.x_range=p2.x_range=p3.x_range=p4.x_range
p1.y_range=p2.y_range=p3.y_range=p4.y_range
In [17]:
wtf=row(p1,p2,p3,p4)
show(wtf)

Linking selections

  • same data source ColumnDataSource(df)
  • because those 4 plots share the same data source, they will be share the same selection
In [18]:
p1=figure(plot_width=250, plot_height=250, title='sepal_L vs. petal_L',\
          tools='box_select, crosshair, lasso_select')
p2=figure(plot_width=250, plot_height=250, title='sepal_W vs. petal_W')
p3=figure(plot_width=250, plot_height=250, title='sepal_L vs. sepal_W')
p4=figure(plot_width=250, plot_height=250, title='petal_L vs. petal_W')

p1.circle(x='sepal_length',y='petal_length',source=data,alpha=0.6)
p2.square(x='sepal_width',y='petal_width',source=data,color='red',alpha=0.6)
p3.x(x='sepal_length',y='petal_length',source=data,color='green',alpha=0.6)
p4.diamond(x='petal_length',y='petal_width',source=data,color='purple',alpha=0.6)
Out[18]:
<bokeh.models.renderers.GlyphRenderer at 0x7fd77e381610>
In [19]:
wtf=row(p1,p2,p3,p4)
show(wtf)

Annotations and guides

  • Help relate scale information
    • Axes, Grids (default)
  • Explain the visual encodings
    • Legends
  • Drill down into details that not visible in the plot
    • Hover Tooltips
In [20]:
from bokeh.models import LinearColorMapper
In [21]:
flowers['species'].value_counts()
Out[21]:
setosa        50
versicolor    50
virginica     50
Name: species, dtype: int64
In [22]:
mapper={'setosa':'silver','versicolor':'gold','virginica':'cyan'}
prepared=[mapper[i] for i in flowers['species']]
In [23]:
flowers['add_color']=flowers['species'].map(mapper)
In [24]:
flowers.head(1)
Out[24]:
sepal_length sepal_width petal_length petal_width species add_color
0 5.1 3.5 1.4 0.2 setosa silver
In [25]:
data2=ColumnDataSource(flowers)
In [26]:
p=figure(plot_width=700, plot_height=300, title='sepal_L vs. petal_L',\
                   tools='box_select, crosshair, lasso_select',x_range=(5,7))

p.circle(x='sepal_length',y='petal_length',\
          alpha=.9, size=5, color='add_color',\
        legend='species',source=data2)
p.legend.location='bottom_right'
p.legend.background_fill_color='red'
p.legend.background_fill_alpha=.2
show(p)

Hover Tooltips

In [27]:
from bokeh.models import HoverTool
In [28]:
flowers.head(1)
Out[28]:
sepal_length sepal_width petal_length petal_width species add_color
0 5.1 3.5 1.4 0.2 setosa silver
In [29]:
hover=HoverTool(tooltips=[('name','@species'),('longth','@petal_length'),('width','@petal_width')])
In [30]:
pl=figure(plot_width=400, plot_height=400,tools=[hover,'pan','wheel_zoom','save'])
pl.circle(x='petal_length',y='petal_width',\
          alpha=0.6, size=15, color='add_color',\
        legend='species',source=data2)
show(pl)
In [ ]:
 

Leave a Reply

Your email address will not be published.