【问题标题】:Add custom tooltips on pie chart in Bokeh and display correctly在 Bokeh 中的饼图上添加自定义工具提示并正确显示
【发布时间】:2017-07-26 14:43:15
【问题描述】:

我在尝试使用bokeh.charts.DonutHoverTool.tooltips 中添加自定义值时遇到了一些问题。

我正在尝试在HoverTool.tooltips 中添加百分比标记。我确信在饼图中显示百分比值以及绝对值是很常见的做法,因为这样可以提高可读性。

由于bokeh.charts.Donut 是高级图表API,我似乎无法使自定义HoverTool.tooltipsdoc 中所示那样工作。

from bokeh.plotting import output_notebook
from bokeh.charts import show,Donut
from bokeh.models import HoverTool
import pandas as pd
output_notebook()

d = {'posa': ['US','IT','FR','ES','DE','GB','CA','BE','AU','NL','NO','SE','DK'],
 'values': [4464, 989, 875, 824, 773, 733, 598, 307, 140, 132, 118, 112, 65]}
df = pd.DataFrame(d)
df['percentage'] = df['values']/df['values'].sum()

pie_chart = Donut(df,title='Distribution of unmatched by POSa',label='posa',values='values',plot_width=700,plot_height=700,)
hover = pie_chart.select(dict(type=HoverTool))
hover.tooltips = [('percentage', '@percentage'),('value','@values')]
show(pie_chart)

上面的代码在工具提示中生成了带有 percentage: ??? 的图表。

我想修正百分比标签并正确显示。

任何帮助将不胜感激!

谢谢。

【问题讨论】:

    标签: python jupyter-notebook bokeh


    【解决方案1】:

    我亲自动手编写了一个类似于bokeh.charts 中高级图表 API 的 BuilderClass。

    类和功能:

    from numpy import pi
    from random import shuffle
    from math import sin,cos
    from bokeh.plotting import ColumnDataSource,output_notebook,figure
    from bokeh.charts import show,Donut
    from bokeh.models import HoverTool,Text
    from bokeh import palettes
    import pandas as pd
    
    output_notebook()
    
    class CustomPieBuilder:
        green ="#50ee70"
        red = "#ff7070"
        x_range = 1.1
        y_range = 1.1
    
        def __init__(self,df,label_name,column_name,tools='hover',tooltips=None,
                     reverse_color=False,colors=None,random_color_order=False,
                     plot_width=400,plot_height=400,title='Untitled',*args,**kwargs):
            p = self.setup_figure(tools,plot_width,plot_height,title)
            df = self.add_columns_for_pie_chart(df,column_name,colors,reverse_color,random_color_order)
            self.df = df
            self.plot_pie(p,df,label_name,*args,**kwargs)
            if tooltips:
                self.set_hover_tooltip(p,tooltips)
    
            self.add_text_label_on_pie(p,df,label_name)
            self.plot = p
    
        def setup_figure(self,tools,plot_width,plot_height,title):
            p = figure(
                x_range=(-self.x_range, self.x_range),
                y_range=(-self.y_range, self.y_range),
                tools=tools,
                plot_width=plot_width,
                plot_height=plot_height,
                title=title,
            )
            p.axis.visible = False
            p.xgrid.grid_line_color = None
            p.ygrid.grid_line_color = None
            return p
    
        @staticmethod
        def plot_pie(p,df,label_name,*args,**kwargs):
            for key, _df in df.groupby(label_name):
                source = ColumnDataSource(_df.to_dict(orient='list'))
                p.annular_wedge(
                    x=0,
                    y=0,
                    inner_radius=0,
                    outer_radius=1,
                    start_angle='starts',
                    end_angle='ends',
                    color='colors',
                    source=source,
                    legend=key,
                    *args,**kwargs)
    
        @staticmethod
        def set_hover_tooltip(p,tooltips):
            hover = p.select({'type':HoverTool})
            hover.tooltips = tooltips
    
        @staticmethod
        def add_columns_for_pie_chart(df,column_name,colors=None,reverse_color=False,random_color_order=False):
            r = 0.7
            df = df.copy()
            column_sum = df[column_name].sum()
            df['percentage'] = (df[column_name]/column_sum)
            percentages = [0]  + df['percentage'].cumsum().tolist()
            df['starts'] = [p * 2 * pi for p in percentages[:-1]]
            df['ends'] = [p * 2 * pi for p in percentages[1:]]
    
            df['middle'] = (df['starts'] + df['ends'])/2
            df['text_x'] = df['middle'].apply(cos)*r
            df['text_y'] =df['middle'].apply(sin)*r 
            df['text_angle'] = 0.0
    
            if colors:
                df['colors'] = colors
            else:
                if 'colors' not in df:
                    reverse_color = -1 if reverse_color else 1
                    colors = palettes.viridis(len(df))[::reverse_color]
                    if random_color_order:
                        shuffle(colors)
                    df['colors'] = colors
            return df
    
        @staticmethod
        def add_text_label_on_pie(p,df,label_name):
            source=ColumnDataSource(df.to_dict(orient='list'))
            txt = Text(x="text_x", y="text_y", text=label_name, angle="text_angle",
                   text_align="center", text_baseline="middle",
                   text_font_size='10pt',)
            p.add_glyph(source,txt)
    
    def build_plot(df,label_name,column_name,tools='hover',tooltips=None,
                     reverse_color=False,colors=None,random_color_order=False,
                     plot_width=400,plot_height=400,title='Untitled',*args,**kwargs):
    
        customPie = CustomPieBuilder(df,label_name,column_name,tools,tooltips,
                     reverse_color,colors,random_color_order,
                     plot_width,plot_height,title,*args,**kwargs)
    
        return customPie.plot
    

    代码:

    d = {'posa': ['US','IT','FR','ES','DE','GB','CA','BE','AU','NL','NO','SE','DK'],
     'values': [4464, 989, 875, 824, 773, 733, 598, 307, 140, 132, 118, 112, 65]}
    df = pd.DataFrame(d)
    
    p = build_plot(
        df,
        'posa',
        'values',
        tooltips=[('percentage', '@percentage{0.00%}'), ('POSa', '@posa'), ('count','@values')],
        title='Testing',
        reverse_color=True,
        random_color_order=True,
        plot_height=700,
        plot_width=700)
    
    show(p)
    

    图表:

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多