Bokeh-Boostrap交互

2020年06月29日 10点热度 0人点赞 0条评论
import numpy as np
from bokeh.plotting import figure, show, output_notebook
from bokeh.layouts import gridplot
output_notebook()
from bokeh.themes import built_in_themes
from bokeh.io import curdoc
curdoc().theme = 'dark_minimal'
from math import pi
import pandas as pd
from bokeh.palettes import Category20c
from bokeh.transform import cumsum
# 数据
x = {
    'United States': 157,
    'United Kingdom': 93,
    'Japan': 89,
    'China': 63,
    'Germany': 44,
    'India': 42,
    'Italy': 40,
    'Australia': 35,
    'Brazil': 32,
    'France': 31,
    'Taiwan': 31,
    'Spain': 29
}
data = pd.Series(x).reset_index(name='value').rename(columns={'index':'country'})
data['angle'] = data['value']/data['value'].sum() * 2*pi
data['color'] = Category20c[len(x)]
# 画布
p = figure(plot_height=350, title="Pie Chart",
#            toolbar_location=None,
           tools="save,hover", tooltips="@country: @value", x_range=(-0.5, 1.0), sizing_mode="scale_width")
# 绘图
p.wedge(x=0, y=1, radius=0.4,
        start_angle=cumsum('angle', include_zero=True), end_angle=cumsum('angle'),
        line_color="white", fill_color='color', legend='country', source=data)
# 其他
p.axis.axis_label=None
p.axis.visible=False
p.grid.grid_line_color = None
# 显示
# show(p)
# html组件1
from bokeh.embed import components
script_01, div_01 = components(p)
div_01
'\n<div class="bk-root" id="9c63edd1-d65b-4d7f-bf04-32cfeddd54c7" data-root-id="1944"></div>'
# 画布
p = figure(plot_height=350, title="Donut Chart", 
#            toolbar_location=None,
           tools="save,hover", tooltips="国家@country: 数值@value", sizing_mode="scale_width")  # 已支持中文,鼠标悬停饼图显示数据
# 绘图
p.annular_wedge(x=0, y=1, outer_radius=0.4,inner_radius=0.3, 
        # use cumsum to cumulatively sum the values for start and end angles
        start_angle=cumsum('angle', include_zero=True), end_angle=cumsum('angle'),
        line_color="white", fill_color='color', legend='country', source=data)
# 其他
p.axis.axis_label=None
p.axis.visible=False
p.grid.grid_line_color = None
# 显示
# show(p)
# html组件2
from bokeh.embed import components
script_02, div_02 = components(p)
div_02
'\n<div class="bk-root" id="92f91216-85ed-47f5-b5a1-63b43258d96b" data-root-id="2020"></div>'
from bokeh.models import ColumnDataSource, NumeralTickFormatter, SingleIntervalTicker
from bokeh.sampledata.us_marriages_divorces import data
# 数据
data = data.interpolate(method='linear', axis=0).ffill().bfill()
source = ColumnDataSource(data=dict(
    year=data.Year.values,
    marriages=data.Marriages_per_1000.values,
    divorces=data.Divorces_per_1000.values,
))
# 工具条
TOOLS = 'pan,wheel_zoom,box_zoom,reset,save'
# 画布
p = figure(tools=TOOLS,  plot_height=300,
           tooltips='<font face="Arial" size="3">@$name{0.0} $name per 1,000 people in @year</font>', sizing_mode="scale_width")
# 其他自定义属性
p.hover.mode = 'vline'
p.xaxis.ticker = SingleIntervalTicker(interval=10, num_minor_ticks=0)
p.yaxis.formatter = NumeralTickFormatter(format='0.0a')
p.yaxis.axis_label = '# per 1,000 people'
p.title.text = '144 years of marriage and divorce in the U.S.'
# 绘图
p.line('year', 'marriages', color='#1f77b4', line_width=3, source=source, name="marriages")
p.line('year', 'divorces', color='#ff7f0e', line_width=3, source=source, name="divorces")
# 显示
# show(p)
# html组件3
from bokeh.embed import components
script_03, div_03 = components(p)
div_03
'\n<div class="bk-root" id="e63251db-da80-4dc8-99ee-02c63a21672f" data-root-id="2097"></div>'
from math import pi
import pandas as pd
from bokeh.models import LinearColorMapper, BasicTicker, PrintfTickFormatter, ColorBar
from bokeh.sampledata.unemployment1948 import data
# 数据
data['Year'] = data['Year'].astype(str)
data = data.set_index('Year')
data.drop('Annual', axis=1, inplace=True)
data.columns.name = 'Month'
years = list(data.index)
months = list(data.columns)
df = pd.DataFrame(data.stack(), columns=['rate']).reset_index()
# 配色
colors = ["#75968f", "#a5bab7", "#c9d9d3", "#e2e2e2", "#dfccce", "#ddb7b1", "#cc7878", "#933b41", "#550b1d"]
mapper = LinearColorMapper(palette=colors, low=df.rate.min(), high=df.rate.max())
# 工具条
TOOLS = "hover,save,pan,box_zoom,reset,wheel_zoom"
# 画布
p = figure(title="US Unemployment ({0} - {1})".format(years[0], years[-1]),
           x_range=years, y_range=list(reversed(months)),
           x_axis_location="above", plot_width=900, plot_height=400,
           tools=TOOLS, toolbar_location='below',
           tooltips=[('date', '@Month @Year'), ('rate', '@rate%')], sizing_mode="scale_width")
# 其他
p.grid.grid_line_color = None
p.axis.axis_line_color = None
p.axis.major_tick_line_color = None
p.axis.major_label_text_font_size = "5pt"
p.axis.major_label_standoff = 0
p.xaxis.major_label_orientation = pi / 3
# 绘图
p.rect(x="Year", y="Month", width=1, height=1,
       source=df,
       fill_color={'field': 'rate', 'transform': mapper},
       line_color=None)
# 色值条
color_bar = ColorBar(color_mapper=mapper, major_label_text_font_size="5pt",
                     ticker=BasicTicker(desired_num_ticks=len(colors)),
                     formatter=PrintfTickFormatter(format="%d%%"),
                     label_standoff=6, border_line_color=None, location=(0, 0))
p.add_layout(color_bar, 'right')
# 显示
# html组件4
from bokeh.embed import components
script_04, div_04 = components(p)
div_04
'\n<div class="bk-root" id="4b354329-160a-4f27-9291-3b17d4b07e2a" data-root-id="2181"></div>'
import networkx as nx
from bokeh.io import show, curdoc
from bokeh.layouts import Row, Column
from bokeh.models import Plot, Range1d, MultiLine, Circle, HoverTool, TapTool, BoxSelectTool
from bokeh.models.graphs import from_networkx, NodesAndLinkedEdges, EdgesAndLinkedNodes
from bokeh.palettes import Spectral4
G=nx.karate_club_graph()
def create_graph(layout_func, inspection_policy=None, selection_policy=None, **kwargs):

    plot = Plot(plot_width=400, plot_height=400,
                x_range=Range1d(-1.1,1.1), y_range=Range1d(-1.1,1.1))
    graph_renderer = from_networkx(G, layout_func, **kwargs)

    graph_renderer.node_renderer.glyph = Circle(size=15, fill_color=Spectral4[0])
    graph_renderer.node_renderer.selection_glyph = Circle(size=15, fill_color=Spectral4[2])
    graph_renderer.node_renderer.hover_glyph = Circle(size=15, fill_color=Spectral4[1])

    graph_renderer.edge_renderer.glyph = MultiLine(line_color="#CCCCCC", line_alpha=0.8, line_width=5)
    graph_renderer.edge_renderer.selection_glyph = MultiLine(line_color=Spectral4[2], line_width=5)
    graph_renderer.edge_renderer.hover_glyph = MultiLine(line_color=Spectral4[1], line_width=5)

    graph_renderer.inspection_policy = inspection_policy
    graph_renderer.selection_policy = selection_policy

    plot.renderers.append(graph_renderer)

    return plot

plot_1 = create_graph(nx.circular_layout, inspection_policy=NodesAndLinkedEdges(), scale=1, center=(0,0))
plot_1.title.text = "Circular Layout (NodesAndLinkedEdges inspection policy)"
plot_1.add_tools(HoverTool(tooltips=None))

plot_2 = create_graph(nx.spring_layout, selection_policy=NodesAndLinkedEdges(), scale=2, center=(0,0))
plot_2.title.text = "Spring Layout (NodesAndLinkedEdges selection policy)"
plot_2.add_tools(TapTool(), BoxSelectTool())

plot_3 = create_graph(nx.random_layout, inspection_policy=EdgesAndLinkedNodes(), center=(0,0))
plot_3.title.text = "Random Layout (EdgesAndLinkedNodes inspection policy)"
plot_3.add_tools(HoverTool(tooltips=None))

plot_4 = create_graph(nx.fruchterman_reingold_layout, selection_policy=EdgesAndLinkedNodes(), scale=2, center=(0,0), dim=2)
plot_4.title.text = "FR Layout (EdgesAndLinkedNodes selection policy)"
plot_4.add_tools(TapTool())

layout = Column(Row(plot_1, plot_2), Row(plot_3, plot_4))
# show(layout)
# html组件5
from bokeh.embed import components
script_05, div_05 = components(layout)
div_05
'\n<div class="bk-root" id="7311636e-a824-4fcc-88cc-dcf2736ada59" data-root-id="2480"></div>'
# html源码
html = '''
<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8"> 
    <title>Bokeh embed Bootstrap 实例</title>
    <link rel="stylesheet" href="https://cdn.staticfile.org/twitter-bootstrap/3.3.7/css/bootstrap.min.css">
    <script src="https://cdn.staticfile.org/jquery/2.1.1/jquery.min.js"></script>
    <script src="https://cdn.staticfile.org/twitter-bootstrap/3.3.7/js/bootstrap.min.js"></script>

    <link rel="stylesheet" href="https://cdn.pydata.org/bokeh/release/bokeh-1.1.0.min.css">
    <link rel="stylesheet" href="https://cdn.pydata.org/bokeh/release/bokeh-widgets-1.1.0.min.css">   
    <script src="https://cdn.pydata.org/bokeh/release/bokeh-1.1.0.min.js"></script>
    <script src="https://cdn.pydata.org/bokeh/release/bokeh-widgets-1.1.0.min.js"></script>
</head>
<body style='background-color:black'>
<div style='margin:0 15px 0 15px'>
    <div class="row">
        <div class="col-md-6">
        {div_01}
        </div>
        <div class="col-md-6">
        {div_02}
        </div>
    </div>
    <div class="row">
        <div class="col-md-6">
            {div_03}
       </div>
        <div class="col-md-6"> 
            {div_04}
        </div>
    </div>
    <div class="row">
        <div class="col-md-6 col-md-offset-3">
        {div_05}
        </div>
    </div>
</div>
{script_01}
{script_02}
{script_03}
{script_04}
{script_05}
</body>
</html>'''.format(div_01=div_01,script_01=script_01,div_02=div_02,script_02=script_02,
                  div_03=div_03,script_03=script_03,div_04=div_04,script_04=script_04,
                  div_05=div_05,script_05=script_05)
with open("Bokeh embed Bootstrap2.html", "w", encoding='utf-8') as f:
    f.write(html)# 保存为html文件
未经允许不得转载!Bokeh-Boostrap交互

update

纸上得来终觉浅, 绝知此事须躬行。